Vier Bildschirmfotos, vier Auftraege. Vor dem Bauen gemessen
(server/mess-sichtbarkeit.mjs): alle Bereiche, alle vier Rollen.
ZWEI FEHLER, DIE NIEMAND GEMELDET HAETTE
Beide sahen auf DogFathers eigenem Bildschirm vollkommen richtig aus --
und das ist das Tueckische: Ein leeres Brett sieht nicht nach Fehler
aus, sondern nach "da ist eben noch nichts".
1. DIE FREIGABE. "Was ansteht" und "Highlights" zeigen der Community
nur, was freigegeben ist. Ein aus dem Vorschlagskasten uebernommener
Eintrag hatte keine Freigabe. Gemessen:
Brett DogFather rechte Hand Modi Community
ansteht 4 4 4 0
highlight 3 3 3 0
Filipe konnte fuellen, so viel er wollte -- fuer die Community
blieben genau die zwei Bretter leer, auf die es ankommt. Wer aus dem
Team uebernimmt, gibt jetzt zugleich frei: Die Freigabe fragt "hat
das Team diesen Text gesehen?", und die Antwort ist beim Uebernehmen
ja. Eine zweite Entscheidung daneben waere keine Sicherheit, sondern
ein Klick.
2. TEAM_DOGI_ROLLEN IST {hand, modi} -- OHNE "admin". Die
Sichtbarkeitsregel fuer Team Dogi lautete damit woertlich "Eintraege
von hand oder modi". Folge: ALLES, was DogFather in Live, Technik,
Community, Ideen, Angebote oder Rueckmeldung schreibt, war fuer sein
eigenes Team unsichtbar. Das ist nicht erst seit dem Startkatalog so
-- der hat es nur sichtbar gemacht, weil vorher ueberall Null stand
und Null gleich Null aussieht, egal aus welchem Grund.
Die Liste wird genau dort erweitert, wo es um Sichtbarkeit geht --
NICHT in TEAM_DOGI_ROLLEN selbst: Diese Menge entscheidet auch,
welches Haus jemand bewohnt. Ein Eintrag dort haette DogFather
stillschweigend zur Crew umgezogen.
113 FERTIGE INHALTE IN DEN LEEREN KATEGORIEN
Gemessen waren elf Bereiche ausserhalb des Treffs komplett leer -- fuer
JEDE Rolle. Der Startkatalog kannte nur die sieben Treff-Bretter; die
Oberflaeche war die ganze Zeit bereit, es fehlten nur die Texte.
workspace-arbeit-start.js fuellt neun davon: Live, Content, Technik,
Community, Schutz, Ideen, Rueckmeldung, Angebote, Agentur.
"talente" und "entwicklung" bekommen ABSICHTLICH nichts: Dort waere ein
"fertiger Inhalt" ein erfundener Mensch -- ein Testdatensatz in einem
System, das echte Menschen bewertet. Die Talente-Seite bekommt ihre
Hilfe anders (siehe unten).
DER ENTWICKLUNGSKATALOG: 28 -> 68 PUNKTE, VIERTE STUFE
Filipe: "wieso ist da immer noch nicht perfektionniert wie bei den
anderen mit fortgeschritten und so, und VIIIIIEEEELLLLLL mehr aufgaben."
* Neue Stufe "Fortgeschritten" zwischen "nach ein paar Monaten" und
"wofuer man jemanden fragt" -- genau die Mitte fehlte.
* Stufenleiter als FILTER ueber den Kategorien, wie die Checkliste es
seit dem 10.09. vormacht. Aus r.erwartung gebaut, nicht aufgezaehlt.
* Zwei neue Bloecke, die Filipe ausdruecklich wollte: "Clips, Schnitt
und Kommentare" und "Waehrend der Stream laeuft" -- seine
Wunschkategorien vom 17.09. ("videos schneide, kommentieren,
markierungen").
* Keine Note, keine Punktzahl, keine Rangliste. Unveraendert.
DAS BEFINDEN: 6 -> 12 FRAGEN, UND SIE MELDET SICH VON SELBST
Den 14-Tage-Rhythmus gab es schon -- er wirkte aber nur, WENN jemand die
Seite aufmachte. Wer sie vergisst, wurde nie wieder gefragt: Das war
eine Anzeige, keine Anfrage. Jetzt kommt sie ueber dasselbe Push-System
wie faellige Aufgaben, hoechstens einmal je sieben Tage, und sie fragt
rhythmus() aus workspace-befinden.js -- dieselbe Funktion wie die Seite,
keine zweite Formel daneben.
Sechs neue Fragen zu Erholung, Sinn, Klarheit, Anfeindung, Entwicklung
und dem Blick nach vorn, jede mit ihrer Einordnung.
Und an acht Stellen stand "sechs Fragen" ueber zwoelf Fragen -- wo ein
Skript den Text baut, wird jetzt gezaehlt; in den festen Seiten steht
gar keine Zahl mehr.
DIE TALENTE-SEITE, WENN NIEMAND DARAUF STEHT
Statt "Noch niemand auf der Liste" stehen dort jetzt die fuenf Gruppen
mit ihren 21 Anzeichen -- die gab es laengst, sie waren auf der leeren
Seite nur nie zu sehen. Dazu der Weg in beide Richtungen: woher ein
Talent kommt (der Treff) und wo es endet (die Entwicklung).
DIE PRUEFUNG (server/pruef-alle-sehen-es.mjs, 42 Pruefungen)
Sie prueft BEIDE Haelften von Filipes Satz. Nur zu zaehlen, ob alle
alles sehen, waere gruen, wenn man saemtliche Schranken entfernte --
Abschnitt 4 belegt, dass 19 Bereich-Rollen-Paare zu bleiben und die
Community an keinen der elf Arbeitsbereiche kommt.
ZWEI GEGENPROBEN, weil 42 von 42 im ersten Lauf kein Beweis ist:
a) "admin" aus der Team-Sicht entfernen -> 13 Pruefungen rot
b) Freigabe beim Uebernehmen abschalten -> 2 rot, genau ansteht
und highlight
Jede trifft ihr Ziel und nicht alles.
UND EINE LUECKE IN EINER ALTEN PRUEFUNG
pruef-deutsche-texte war gruen -- und hatte die 113 neuen Texte, die 40
neuen Entwicklungspunkte und die 6 neuen Fragen nie gesehen: Sie stehen
in Dateien, die sie nicht kannte. Jetzt 391 statt 174 geprueften
Texten. (Meine erste Untergrenze stand auf 400 und war sofort rot --
geraten statt gemessen.)
Stempel 202609171318.
Co-Authored-By: Claude Opus 5 <[email protected]>
539 lines
24 KiB
JavaScript
539 lines
24 KiB
JavaScript
/* =====================================================================
|
||
Wie geht's dir? (15.09.2026)
|
||
|
||
Filipe, mit dem Bildschirmfoto der Kachel: *„ich will dass du diese
|
||
seite perfektionnierst, denn gerade wenn ich drauf drücke geht die
|
||
entwicklungsseite auf."*
|
||
|
||
Er hat recht, und es war schlimmer als ein falscher Verweis: Die
|
||
Kachel verspricht „sechs Fragen – die Antworten sieht nur du" und
|
||
öffnete eine Seite mit Namen und Beobachtungen über andere Menschen.
|
||
Wer ihr glaubt und draufdrückt, sieht im ersten Moment das Gegenteil
|
||
dessen, was draufsteht.
|
||
|
||
---------------------------------------------------------------------
|
||
EINE SEITE, EIN ZWECK
|
||
|
||
`entwicklung.html` bediente zwei Fragen: „wie geht es dem Team?" und
|
||
„wie geht es mir?". Das ist eine Seite zu wenig. Die sechs Fragen
|
||
haben jetzt ihre eigene — und `entwicklung.html` wird dadurch selbst
|
||
einfacher, weil sie nur noch eine Sache tut.
|
||
|
||
---------------------------------------------------------------------
|
||
WAS DIE RECHERCHE ERGEBEN HAT (15.09.2026)
|
||
|
||
Zu Puls-/Befindensabfragen in kleinen Teams sagen die Quellen
|
||
übereinstimmend dreierlei:
|
||
|
||
1. KURZ. Fünf bis fünfzehn Fragen, unter zwei Minuten. Sechs sind
|
||
also richtig — daran ändert sich nichts.
|
||
|
||
2. WIEDERHOLT. Monatlich oder zweiwöchentlich. Genau das fehlte:
|
||
Bisher beantwortete man die sechs Fragen EINMAL, und die Antwort
|
||
stand für immer. Ein Befinden von vor drei Monaten ist keine
|
||
Auskunft mehr, sondern ein Andenken.
|
||
|
||
3. DER VERLAUF IST DIE AUSKUNFT, nicht der Einzelwert. „Niedrige
|
||
Energie über mehrere Wochen" ist das Warnzeichen — ein einzelnes
|
||
„da hakt es" ist ein schlechter Tag.
|
||
|
||
Deshalb zwei Dinge neu: ein RHYTHMUS (nach 14 Tagen wird wieder
|
||
gefragt) und ein VERLAUF, den nur die Person selbst sieht.
|
||
|
||
Quellen:
|
||
https://www.specific.app/blog/pulse-survey-questions-best-questions-for-burnout-to-detect-and-address-employee-engagement-risk
|
||
https://formbricks.com/blog/pulse-survey-questions
|
||
https://www.vantagecircle.com/en/blog/pulse-surveys/
|
||
|
||
---------------------------------------------------------------------
|
||
DER VERLAUF GEHÖRT IHR ALLEIN
|
||
|
||
Er wird in einer eigenen Tabelle geführt, und kein anderer Weg im
|
||
Haus liest sie. Die Ampel (wie viele es gerade schwer haben) zählt
|
||
weiterhin nur den AKTUELLEN Stand und kennt keine Namen — daran
|
||
ändert der Verlauf nichts.
|
||
|
||
Das ist kein Nebensatz: Eine Verlaufsakte über das Befinden eines
|
||
Menschen ist das Empfindlichste, was dieses Haus speichern kann. Sie
|
||
existiert nur, weil sie IHM hilft, sein eigenes Muster zu sehen.
|
||
===================================================================== */
|
||
|
||
import express from "express";
|
||
import { db, sitzungLesen, protokolliere, echteIp } from "./workspace.js";
|
||
import {
|
||
ENTWICKLUNG_BLOECKE, ENTWICKLUNG_PUNKTE, ENTWICKLUNG_STUFEN,
|
||
} from "./workspace-entwicklungs-punkte.js";
|
||
import { tabellen as entwicklungTabellen } from "./workspace-entwicklung.js";
|
||
|
||
export const befindenRouter = express.Router();
|
||
|
||
/** Nach wie vielen Tagen wieder gefragt wird.
|
||
*
|
||
* 14 Tage — zweiwöchentlich, das untere Ende dessen, was die Quellen
|
||
* empfehlen (monatlich bis zweiwöchentlich). Häufiger wäre
|
||
* Umfragemüdigkeit: Wer jede Woche gefragt wird, klickt irgendwann
|
||
* dasselbe an wie beim letzten Mal, ohne nachzudenken — und dann misst
|
||
* die Abfrage nur noch sich selbst. */
|
||
export const RHYTHMUS_TAGE = 14;
|
||
|
||
/** So viele frühere Antworten bekommt die Person zu sehen.
|
||
*
|
||
* Sechs Stände sind drei Monate — lang genug, um ein Muster zu sehen,
|
||
* kurz genug, dass es kein Archiv wird. */
|
||
export const VERLAUF_MAX = 6;
|
||
|
||
const jetzt = () => new Date().toISOString();
|
||
|
||
let bereit = false;
|
||
function tabellen() {
|
||
if (bereit) return;
|
||
db().exec(`
|
||
/* DER VERLAUF DES EIGENEN BEFINDENS.
|
||
|
||
Eigene Tabelle und nicht „entwicklung_stand“: Dort steht der
|
||
AKTUELLE Stand, einer je Punkt und Beurteiler, und der wird
|
||
ueberschrieben. Genau das ist dort richtig -- eine Beobachtung
|
||
ueber einen Menschen soll aktuell sein, nicht historisch.
|
||
|
||
Hier ist es umgekehrt: Der Verlauf IST die Auskunft. Zwei
|
||
verschiedene Beduerfnisse, zwei Tabellen. Sie in eine zu zwingen
|
||
hiesse, eines von beiden falsch zu machen.
|
||
|
||
KEIN von_id: Was hier steht, hat die Person ueber sich selbst
|
||
gesagt. Eine Spalte fuer "wer hat das eingetragen" waere die
|
||
Einladung, eines Tages auch jemand anderen eintragen zu lassen. */
|
||
CREATE TABLE IF NOT EXISTS befinden_verlauf (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
person_id INTEGER NOT NULL REFERENCES personen(id) ON DELETE CASCADE,
|
||
runde TEXT NOT NULL, -- Zeitpunkt der Runde, alle sechs teilen ihn
|
||
schluessel TEXT NOT NULL,
|
||
stufe TEXT NOT NULL,
|
||
am TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_befinden_person
|
||
ON befinden_verlauf (person_id, runde);
|
||
`);
|
||
/* UND DIE TABELLE, AUS DER DIE ANTWORTEN KOMMEN.
|
||
|
||
Sie wird hier nicht angelegt, sondern angefordert: Die sechs
|
||
Antworten stehen in `entwicklung_stand`, und die legt die
|
||
Entwicklungsseite an -- beim ersten Aufruf, nicht beim Start.
|
||
Wer die neue Seite oeffnete, bevor irgendjemand die
|
||
Entwicklungsseite besucht hatte, bekam deshalb "no such table"
|
||
und eine 503. Gefunden hat das die Pruefung, nicht das Lesen. */
|
||
entwicklungTabellen();
|
||
bereit = true;
|
||
}
|
||
|
||
function angemeldet(req, res, next) {
|
||
const person = sitzungLesen(req);
|
||
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
|
||
req.person = person;
|
||
try { tabellen(); } catch (f) {
|
||
console.error("[befinden] Tabellen:", f?.message);
|
||
return res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||
}
|
||
next();
|
||
}
|
||
|
||
/** Der Block mit den sechs Fragen. Er ist als einziger `nurSelbst`. */
|
||
function block() {
|
||
return ENTWICKLUNG_BLOECKE.find((b) => b.nurSelbst) || null;
|
||
}
|
||
|
||
/** Wann war die letzte vollständige Runde — und ist wieder Zeit?
|
||
*
|
||
* EXPORTIERT SEIT DEM 17.09.2026, damit die automatische Erinnerung
|
||
* (workspace-push.js) DIESELBE Rechnung benutzt. Eine zweite Formel
|
||
* daneben ("älter als 14 Tage") wäre die Falle, die in diesem Haus
|
||
* schon mehrfach zugeschlagen hat: Sie stimmt am Tag des Schreibens
|
||
* und läuft danach auseinander -- und zwar still, weil beide Seiten
|
||
* plausible Zahlen liefern. */
|
||
export function rhythmus(personId) {
|
||
const b = block();
|
||
const gesamt = (ENTWICKLUNG_PUNKTE[b.schluessel] || []).length;
|
||
const letzte = db().prepare(
|
||
`SELECT runde, COUNT(*) AS n FROM befinden_verlauf
|
||
WHERE person_id = ? GROUP BY runde ORDER BY runde DESC LIMIT 1`).get(personId);
|
||
if (!letzte) return { letzte: null, faellig: true, tage: null, vollstaendig: false };
|
||
const tage = Math.floor((Date.now() - Date.parse(letzte.runde)) / 86400000);
|
||
return {
|
||
letzte: letzte.runde,
|
||
tage,
|
||
vollstaendig: letzte.n >= gesamt,
|
||
/* FAELLIG heisst: die letzte Runde ist alt genug -- ODER sie war nie
|
||
fertig. Eine halb beantwortete Runde ist keine Runde. */
|
||
faellig: tage >= RHYTHMUS_TAGE || letzte.n < gesamt,
|
||
};
|
||
}
|
||
|
||
/* =====================================================================
|
||
DIE SEITE
|
||
===================================================================== */
|
||
|
||
befindenRouter.get("/workspace/api/befinden", angemeldet, (req, res) => {
|
||
try {
|
||
const b = block();
|
||
if (!b) return res.status(503).json({ fehler: "kein_block" });
|
||
|
||
const meine = new Map(db().prepare(
|
||
`SELECT schluessel, stufe, anlass, am FROM entwicklung_stand
|
||
WHERE person_id = ? AND von_id = ?`)
|
||
.all(req.person.id, req.person.id).map((z) => [z.schluessel, z]));
|
||
|
||
/* DER VERLAUF -- nach Runden gebuendelt, neueste zuerst. */
|
||
const runden = db().prepare(
|
||
`SELECT runde FROM befinden_verlauf WHERE person_id = ?
|
||
GROUP BY runde ORDER BY runde DESC LIMIT ?`).all(req.person.id, VERLAUF_MAX)
|
||
.map((z) => z.runde);
|
||
const zeilen = runden.length
|
||
? db().prepare(
|
||
`SELECT runde, schluessel, stufe FROM befinden_verlauf
|
||
WHERE person_id = ? AND runde IN (${runden.map(() => "?").join(",")})`)
|
||
.all(req.person.id, ...runden)
|
||
: [];
|
||
const verlauf = runden.map((r) => ({
|
||
runde: r,
|
||
antworten: Object.fromEntries(
|
||
zeilen.filter((z) => z.runde === r).map((z) => [z.schluessel, z.stufe])),
|
||
}));
|
||
|
||
const punkte = (ENTWICKLUNG_PUNKTE[b.schluessel] || []).map((pt) => ({
|
||
...pt, meins: meine.get(pt.schluessel) || null,
|
||
}));
|
||
|
||
res.json({
|
||
block: b,
|
||
stufen: ENTWICKLUNG_STUFEN,
|
||
rhythmus_tage: RHYTHMUS_TAGE,
|
||
rhythmus: rhythmus(req.person.id),
|
||
punkte,
|
||
verlauf,
|
||
/* DIE ANALYSE KOMMT MIT, sie holt sich niemand extra.
|
||
|
||
Kein eigener Weg: Sie wird aus demselben Verlauf gerechnet, der
|
||
hier ohnehin schon steht. Ein zweiter Weg waere eine zweite
|
||
Stelle, an der die Rechte stimmen muessen -- und die zweite ist
|
||
immer die, die etwas durchlaesst. */
|
||
analyse: analyseVon(verlauf, punkte),
|
||
});
|
||
} catch (f) {
|
||
console.error("[befinden] Lesen:", f?.message);
|
||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||
}
|
||
});
|
||
|
||
/** Eine Runde abschließen: alle sechs Antworten wandern in den Verlauf.
|
||
*
|
||
* ALS RUNDE UND NICHT JE KLICK: Ein Verlauf, der jeden einzelnen Klick
|
||
* festhält, zeigt kein Muster, sondern Rauschen — und er würde jedes
|
||
* Zögern mitschreiben. Was zählt, ist der Stand, wenn jemand fertig
|
||
* ist. */
|
||
befindenRouter.post("/workspace/api/befinden/runde", express.json({ limit: "8kb" }),
|
||
angemeldet, (req, res) => {
|
||
try {
|
||
const b = block();
|
||
const punkte = ENTWICKLUNG_PUNKTE[b.schluessel] || [];
|
||
const meine = new Map(db().prepare(
|
||
`SELECT schluessel, stufe FROM entwicklung_stand
|
||
WHERE person_id = ? AND von_id = ?`)
|
||
.all(req.person.id, req.person.id).map((z) => [z.schluessel, z.stufe]));
|
||
|
||
const fehlt = punkte.filter((p) => !meine.has(p.schluessel));
|
||
if (fehlt.length) {
|
||
/* EINE HALBE RUNDE IST KEINE RUNDE. Sie wuerde im Verlauf wie
|
||
ein vollstaendiger Stand aussehen und das Muster verfaelschen. */
|
||
return res.status(400).json({
|
||
fehler: "unvollstaendig", offen: fehlt.length, gesamt: punkte.length,
|
||
});
|
||
}
|
||
|
||
const runde = jetzt();
|
||
const rein = db().prepare(
|
||
`INSERT INTO befinden_verlauf (person_id, runde, schluessel, stufe, am)
|
||
VALUES (?,?,?,?,?)`);
|
||
for (const p of punkte) rein.run(req.person.id, runde, p.schluessel, meine.get(p.schluessel), runde);
|
||
|
||
/* IM PROTOKOLL STEHT NUR, DASS es passiert ist -- nicht was.
|
||
Das Protokoll liest DogFather; die Antworten gehen ihn nichts
|
||
an, und ein "detail" mit Stufen darin waere genau die
|
||
Hintertuer, die es hier nicht geben darf. */
|
||
protokolliere("befinden_runde", {
|
||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||
detail: `${punkte.length} Fragen`,
|
||
});
|
||
|
||
res.status(201).json({ runde, anzahl: punkte.length, rhythmus: rhythmus(req.person.id) });
|
||
} catch (f) {
|
||
console.error("[befinden] Runde:", f?.message);
|
||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||
}
|
||
});
|
||
|
||
/* =====================================================================
|
||
WAS DEIN VERLAUF SAGT (15.09.2026)
|
||
|
||
Filipe: „mach mir auch eine analyse, mach eine perfektion draus. eine
|
||
professionelle auch mit infos und so aus aller welt was tiktok
|
||
angeht. ich will dass es perfekt ist!!!!"
|
||
|
||
---------------------------------------------------------------------
|
||
SIE WIRD GERECHNET, NICHT GESPEICHERT
|
||
|
||
Kein Feld, keine Tabelle, keine Note. Die Analyse entsteht bei jedem
|
||
Abruf neu aus dem Verlauf dieser einen Person — und verlässt das
|
||
Haus damit genauso wenig wie er. DogFather sieht sie nicht; es gibt
|
||
keinen Weg, der sie für jemand anderen ausgibt.
|
||
|
||
---------------------------------------------------------------------
|
||
DREI DINGE, DIE SIE TUT — UND EINES, DAS SIE NICHT TUT
|
||
|
||
1. SIE NENNT DAS MUSTER, nicht den Einzelwert. „Da hakt es" in
|
||
einer Runde ist ein schlechter Tag. Dasselbe in zwei Runden
|
||
hintereinander ist etwas anderes, und genau das ist in der
|
||
Forschung das Warnzeichen.
|
||
|
||
2. SIE ORDNET EIN. Zu jeder der sechs Fragen gibt es einen
|
||
belegten Befund aus der Moderationsarbeit — damit niemand
|
||
denkt, er sei der Einzige, dem das so geht. Das ist der Teil,
|
||
den Filipe „Infos aus aller Welt" nennt.
|
||
|
||
3. SIE SAGT, WAS HILFT. Aus derselben Forschung, und zwar
|
||
Maßnahmen, die die Person oder das Team wirklich umsetzen kann
|
||
— nicht „mehr Selbstfürsorge".
|
||
|
||
4. SIE BEWERTET NICHT. Keine Punktzahl, kein Score, kein
|
||
Ampelgesicht. Eine Zahl über das eigene Befinden lädt dazu ein,
|
||
sie zu verbessern statt ehrlich zu antworten — und ab da misst
|
||
die Abfrage nur noch sich selbst.
|
||
|
||
---------------------------------------------------------------------
|
||
DIE QUELLEN
|
||
|
||
Zu freiwilligen Moderatoren (Reddit, Discord, Facebook):
|
||
„Zu wenig Zeit" und „Streit mit anderen Moderatoren" sind die zwei
|
||
meistgenannten Gründe fürs Aufhören. Burnout entsteht aus der
|
||
Menge, aus persönlichen Angriffen wegen Entscheidungen, aus der
|
||
unsichtbaren emotionalen Arbeit und aus fehlenden Werkzeugen.
|
||
https://news.umich.edu/online-content-moderators-likely-to-experience-burnout-u-m-study-suggests/
|
||
https://arxiv.org/pdf/2502.06985
|
||
|
||
Zu bezahlten Moderatoren bei TikTok und anderen Plattformen:
|
||
Über 80 % der Befragten sagen, ihr Arbeitgeber müsse mehr für ihre
|
||
psychische Gesundheit tun. In der Türkei berichteten TikTok-
|
||
Moderatoren von Traumatisierung, langen Schichten und fehlender
|
||
Begleitung; weltweit organisieren sich Moderatoren dagegen.
|
||
https://restofworld.org/2025/tiktok-moderators-turkey/
|
||
https://www.japantimes.co.jp/news/2025/07/04/world/science-health/content-moderators-mental-trauma/
|
||
https://uniglobalunion.org/news/tech-protocols/
|
||
|
||
Was schützt:
|
||
Pausen und Rotation (niemand ist dauerhaft zuständig), Anschluss
|
||
ans Team (der stärkste Einzelfaktor gegen Belastung), ausdrückliche
|
||
Anerkennung, und ein bekannter Weg für den Ernstfall.
|
||
https://discord.com/safety/understanding-and-avoiding-moderator-burnout
|
||
https://www.zevohealth.com/blog/7-tips-for-managing-content-moderator-wellbeing/
|
||
===================================================================== */
|
||
|
||
/** Ab wie vielen Runden hintereinander ein „hakt" ein Muster ist.
|
||
*
|
||
* ZWEI, nicht drei. Bei vierzehn Tagen Abstand sind zwei Runden ein
|
||
* Monat -- wer einen Monat lang dasselbe meldet, hat keinen schlechten
|
||
* Tag. Drei waeren zehn Wochen, und so lange soll niemand warten. */
|
||
export const MUSTER_AB = 2;
|
||
|
||
/** Zu jeder Frage: der belegte Befund und was dagegen hilft.
|
||
*
|
||
* KEINE ALLGEMEINPLAETZE. Jeder Eintrag gehoert zu genau dieser Frage
|
||
* und stammt aus den Quellen oben. Ein Satz, der zu allen sechs passen
|
||
* wuerde, gehoert hier nicht hinein. */
|
||
export const EINORDNUNG = {
|
||
/* ---- Die sechs vom 17.09.2026 ------------------------------------ */
|
||
"e-ich-abschalten": {
|
||
welt: "Nicht die Menge der Arbeit sagt am besten voraus, ob jemand aufhört, "
|
||
+ "sondern ob die Erholung dazwischen trägt. Wer abschalten kann, hält "
|
||
+ "deutlich mehr aus als jemand mit der halben Schicht und ohne Pause.",
|
||
hilft: "Ein klares Ende ist wirksamer als eine kürzere Schicht: Meldungen aus, "
|
||
+ "Chat zu, und niemand erwartet danach noch eine Antwort. Wer das nicht "
|
||
+ "für sich selbst festlegen kann, braucht jemanden, der es festlegt.",
|
||
},
|
||
"e-ich-sinn": {
|
||
welt: "Das Gefühl, etwas zu bewirken, gilt in Untersuchungen zu Ehrenamt als "
|
||
+ "der stärkste Grund zu bleiben – stärker als Anerkennung und stärker "
|
||
+ "als gute Stimmung im Team.",
|
||
hilft: "Es reicht oft, das Ergebnis überhaupt zu zeigen: Was ist durch die "
|
||
+ "Arbeit der letzten Wochen tatsächlich anders geworden? Wer nur "
|
||
+ "Aufgaben sieht und nie ein Ergebnis, arbeitet ins Leere.",
|
||
},
|
||
"e-ich-klar-was-erwartet": {
|
||
welt: "Unklare Erwartungen sind einer der am besten belegten Auslöser für "
|
||
+ "Erschöpfung – noch vor der Arbeitsmenge. Sie wirken leise, weil "
|
||
+ "niemand sie als Problem benennt.",
|
||
hilft: "Drei Sätze reichen meistens: Was gehört dir, was ausdrücklich nicht, "
|
||
+ "und wann ist es gut genug. Fehlt einer davon, füllt man ihn selbst – "
|
||
+ "und zwar immer mit zu viel.",
|
||
},
|
||
"e-ich-nicht-angefeindet": {
|
||
welt: "Anfeindungen außerhalb der Plattform sind bei Moderatoren verbreiteter "
|
||
+ "als in der Öffentlichkeit bekannt, und sie sind der Punkt, an dem aus "
|
||
+ "Belastung eine Gefahr wird.",
|
||
hilft: "Das ist kein Punkt für eine Umfrage, sondern für ein Gespräch – "
|
||
+ "sofort. Nachrichten sichern (Bildschirmfoto mit Uhrzeit), nichts "
|
||
+ "löschen, und niemand trägt das allein.",
|
||
},
|
||
"e-ich-lerne-dazu": {
|
||
welt: "Ehrenamtliche bleiben deutlich länger, wenn die Tätigkeit ihnen "
|
||
+ "erkennbar etwas mitgibt – eine Fähigkeit, eine Erfahrung, etwas, das "
|
||
+ "auch außerhalb zählt.",
|
||
hilft: "Das entsteht selten von allein. Eine neue Aufgabe, ein Bereich zum "
|
||
+ "Ausprobieren, ein Schnitt- oder Technikthema, das jemand übernimmt: "
|
||
+ "Es kostet nichts und wirkt lange.",
|
||
},
|
||
"e-ich-naechste-monate": {
|
||
welt: "Die Frage nach der eigenen Zukunft im Team ist der beste einzelne "
|
||
+ "Frühindikator, den Befindensabfragen kennen. Sie schlägt an, bevor "
|
||
+ "die anderen Fragen es tun.",
|
||
hilft: "Wenn hier etwas hakt, ist die Antwort nie eine Maßnahme, sondern ein "
|
||
+ "Gespräch – und zwar eines, das fragt statt überzeugt. Wer schon "
|
||
+ "innerlich gegangen ist, lässt sich nicht zurückargumentieren.",
|
||
},
|
||
|
||
"e-ich-menge-passt": {
|
||
welt: "„Zu wenig Zeit“ ist in Untersuchungen zu freiwilligen Moderatoren der "
|
||
+ "meistgenannte Grund fürs Aufhören – noch vor den Inhalten selbst.",
|
||
hilft: "Das ist fast nie eine Frage der Person, sondern der Verteilung: feste "
|
||
+ "Zeiten statt „immer erreichbar“, und eine Schicht, die wirklich endet. "
|
||
+ "Sag es weiter, bevor du es allein löst.",
|
||
},
|
||
"e-ich-niemand-schwierig": {
|
||
welt: "Streit im Team ist der zweithäufigste Grund – und der, über den am "
|
||
+ "wenigsten geredet wird. Er trifft gerade die Teams, die sonst gut laufen.",
|
||
hilft: "Je länger es liegt, desto größer wird es. Ein Gespräch zu dritt, mit "
|
||
+ "jemandem dabei, der nicht Partei ist, löst mehr als zwei Monate Abwarten.",
|
||
},
|
||
"e-ich-weiss-an-wen": {
|
||
welt: "Ein fehlender Eskalationsweg ist in der Forschung kein Wissensproblem, "
|
||
+ "sondern ein Belastungsproblem: Er fühlt sich nicht wie eine offene Frage "
|
||
+ "an, sondern wie Unsicherheit in jeder Schicht.",
|
||
hilft: "Ein Name, nicht „das Team“. Wer im Ernstfall überlegen muss, wen er "
|
||
+ "fragt, fragt niemanden.",
|
||
},
|
||
"e-ich-jemand-zum-reden": {
|
||
welt: "Anschluss ans Team gilt als der stärkste einzelne Schutzfaktor gegen "
|
||
+ "Belastung in der Moderationsarbeit. Umgekehrt arbeiten viele Moderatoren "
|
||
+ "faktisch allein – auch mitten in einem Team.",
|
||
hilft: "Nicht erst, wenn etwas passiert ist. Ein kurzer fester Austausch nach "
|
||
+ "harten Schichten wirkt nachweislich besser als ein Angebot, das man von "
|
||
+ "sich aus annehmen muss.",
|
||
},
|
||
"e-ich-nein-ohne-problem": {
|
||
welt: "Bei bezahlten Moderatoren – auch bei TikTok – sagen über 80 % der "
|
||
+ "Befragten, ihr Arbeitgeber müsse mehr für ihre psychische Gesundheit tun. "
|
||
+ "Wo Nein-Sagen teuer wirkt, bleibt Belastung unsichtbar, bis jemand geht.",
|
||
hilft: "Es geht nicht darum, ob du darfst – sondern wie es sich anfühlt. Wenn "
|
||
+ "es sich teuer anfühlt, ist das eine Auskunft über das Team, nicht über dich.",
|
||
},
|
||
"e-ich-faellt-auf": {
|
||
welt: "Fehlende Anerkennung ist der am häufigsten genannte emotionale Preis "
|
||
+ "dieser Arbeit – die eigentliche Arbeit ist die, die NICHT passiert ist, "
|
||
+ "und die sieht niemand.",
|
||
hilft: "Die billigste Maßnahme überhaupt und die mit der besten Wirkung: "
|
||
+ "ausdrücklich danken, für etwas Bestimmtes, nicht allgemein.",
|
||
},
|
||
};
|
||
|
||
/** Das Muster einer Frage ueber die Runden hinweg -- neueste zuerst. */
|
||
function musterVon(antworten) {
|
||
if (!antworten.length) return { art: "offen", runden: 0 };
|
||
const jetzt = antworten[0];
|
||
let amStueck = 1;
|
||
while (amStueck < antworten.length && antworten[amStueck] === jetzt) amStueck++;
|
||
|
||
if (jetzt === "hakt") {
|
||
return amStueck >= MUSTER_AB
|
||
? { art: "dauerhaft", runden: amStueck }
|
||
: { art: "neu", runden: amStueck };
|
||
}
|
||
/* Vorher hakte es, jetzt nicht mehr -- das gehoert genauso gesagt.
|
||
Eine Auswertung, die nur Schlechtes findet, liest man zweimal. */
|
||
if (antworten.slice(1).includes("hakt")) return { art: "besser", runden: amStueck };
|
||
if (jetzt === "laeuft" && amStueck === antworten.length && antworten.length >= MUSTER_AB) {
|
||
return { art: "traegt", runden: amStueck };
|
||
}
|
||
return { art: "ruhig", runden: amStueck };
|
||
}
|
||
|
||
/** Die Analyse -- aus dem Verlauf gerechnet, fuer niemanden sonst. */
|
||
export function analyseVon(verlauf, punkte) {
|
||
/* EINE EINZIGE RUNDE IST KEINE ENTWICKLUNG. Dann steht hier nichts
|
||
ausser dem Hinweis, dass es beim naechsten Mal etwas zu sehen gibt
|
||
-- eine Auswertung ueber einen Punkt waere geraten. */
|
||
if (!Array.isArray(verlauf) || verlauf.length < MUSTER_AB) {
|
||
return { moeglich: false, runden: verlauf?.length || 0, ab: MUSTER_AB, zeilen: [] };
|
||
}
|
||
|
||
const zeilen = punkte.map((pt) => {
|
||
/* Neueste zuerst -- so kommt der Verlauf ohnehin. */
|
||
const antworten = verlauf.map((r) => r.antworten[pt.schluessel]).filter(Boolean);
|
||
const m = musterVon(antworten);
|
||
const e = EINORDNUNG[pt.schluessel] || {};
|
||
return {
|
||
schluessel: pt.schluessel,
|
||
titel: pt.titel,
|
||
art: m.art,
|
||
runden: m.runden || 0,
|
||
welt: e.welt || null,
|
||
/* WAS HILFT, STEHT NUR DA, WO ES ETWAS ZU TUN GIBT. Ein Rat an
|
||
einer Stelle, die laeuft, ist Laerm -- und er entwertet die
|
||
anderen fuenf. */
|
||
hilft: (m.art === "dauerhaft" || m.art === "neu") ? (e.hilft || null) : null,
|
||
};
|
||
});
|
||
|
||
const dauerhaft = zeilen.filter((z) => z.art === "dauerhaft");
|
||
const neu = zeilen.filter((z) => z.art === "neu");
|
||
const besser = zeilen.filter((z) => z.art === "besser");
|
||
const traegt = zeilen.filter((z) => z.art === "traegt");
|
||
|
||
/* DER SATZ OBEN IST DIE GANZE ANALYSE IN EINER ZEILE. Wer nur ihn
|
||
liest, soll richtig informiert sein. Vier Lagen, vier Saetze -- aus
|
||
demselben Grund, aus dem die Ampel drei hat. */
|
||
let satz;
|
||
if (dauerhaft.length) {
|
||
satz = dauerhaft.length === 1
|
||
? `Eine Sache meldest du seit ${dauerhaft[0].runden} Runden gleich. `
|
||
+ "Das ist kein schlechter Tag mehr – das ist das Muster, auf das es ankommt."
|
||
: `${dauerhaft.length} Sachen melden sich seit mehreren Runden gleich. `
|
||
+ "Das ist selten Zufall und fast nie deine Schuld.";
|
||
} else if (neu.length) {
|
||
satz = neu.length === 1
|
||
? "Eine Sache hakt seit dieser Runde. Einmal ist noch kein Muster – "
|
||
+ "aber der richtige Moment, es anzusprechen, statt zu warten."
|
||
: `${neu.length} Sachen haken seit dieser Runde. Noch kein Muster – `
|
||
+ "aber zwei auf einmal sind einen Satz wert.";
|
||
} else if (besser.length) {
|
||
satz = "Nichts hakt gerade – und "
|
||
+ (besser.length === 1 ? "eine Sache hat sich" : `${besser.length} Sachen haben sich`)
|
||
+ " seit der letzten Runde gelöst. Das gehört genauso festgehalten wie das Gegenteil.";
|
||
} else {
|
||
satz = "Nichts hakt, und über die letzten Runden hat sich daran nichts geändert. "
|
||
+ "Das ist die Antwort, für die diese Seite gebaut ist – nicht die Ausnahme.";
|
||
}
|
||
|
||
return {
|
||
moeglich: true,
|
||
runden: verlauf.length,
|
||
ab: MUSTER_AB,
|
||
satz,
|
||
zeilen,
|
||
/* Abgeleitet, damit die Zahlen nicht neben den Zeilen danebenliegen
|
||
koennen. */
|
||
zahlen: {
|
||
dauerhaft: dauerhaft.length,
|
||
neu: neu.length,
|
||
besser: besser.length,
|
||
traegt: traegt.length,
|
||
},
|
||
};
|
||
}
|