01 / DIE AUSGANGSSITUATION · 3 MINUTEN
„Plane alle offenen Aufgaben bis Freitag um.“
Du gestaltest ein Projektmanagement-Tool. Ein Assistent analysiert 24 Aufgaben und schlägt Termine und Zuständigkeiten vor. Bei drei Aufgaben fehlen Angaben, eine weitere erzeugt einen Ressourcenkonflikt. Wie viel Automatisierung ist unter diesen Bedingungen sinnvoll?
Projektplanung optimieren
24 Aufgaben im fiktiven Szenario: 20 prüfbar · 3 unklar · 1 Konflikt.
Vorschläge vergleichen, Problemfälle klären und eine konkrete Auswahl freigeben. Das ist der Ausgangspunkt für diese Übung; bisher wurde nichts ausgeführt.
Designvergleich, keine Modusumschaltung eines echten Agenten. Die bedienbare Review-Ansicht folgt in der Musterlösung.
Im fiktiven Projekt ist Freitag der 23.10.2026. Die 20 prüfbaren Vorschläge verschieben Termine vom 23. auf den 22.10. und schaffen damit einen Tag Puffer. Bei ihnen gelten Aufwand und Abhängigkeiten als bekannt. Das ist eine Annahme dieser Übung und kein Nachweis, dass der gesamte Plan tatsächlich funktioniert.
Nach Undo und Fehlerprävention in Lektion 9 steht nun die vorgelagerte Frage im Mittelpunkt: Was muss sichtbar und überprüfbar sein, bevor eine Aktion ausgeführt wird?
02 / REVIEW IST MEHR ALS EIN BUTTON
Vier Fragen vor der Freigabe.
- Was wird geändert? Aktuellen und vorgeschlagenen Termin sowie Zuständigkeit gegenüberstellen. Eine allgemeine Erfolgsaussicht ersetzt keine konkrete Änderung.
- Was ist unsicher? Fehlende Daten und Ressourcenkonflikte benennen. „Unklar“ braucht einen Grund und einen nächsten Schritt.
- Was kann ich kontrollieren? Einzelne Vorschläge auswählen, bearbeiten oder ablehnen, ohne die gesamte Prüfung neu zu beginnen.
- Was passiert danach? Ausführungsergebnisse je Änderung zeigen. Erfolgreich, fehlgeschlagen und nicht ausgeführt sind unterschiedliche Zustände.
Die Microsoft Human-AI Interaction Guidelines empfehlen unter anderem einfache Korrekturmöglichkeiten (G9), einen begrenzten Umgang mit Unklarheit (G10) und nachvollziehbare Systementscheidungen (G11). Die konkrete Review-Ansicht dieser Lektion ist ein eigener Gestaltungsvorschlag auf dieser Grundlage. Microsoft: HAX Design Library.
03 / DEINE CHALLENGE · 8 MINUTEN
20 Änderungen effizient prüfen, vier Problemfälle nicht übersehen.
Entwirf in Figma oder React eine Review-Oberfläche für eine Desktop-Ansicht bei 1280 px. Berücksichtige auch, wie dieselben Informationen auf einem schmalen Bildschirm erreichbar bleiben.
- Informationsarchitektur · 2 Minuten: Gruppiere nach Status, Aufgabe oder Änderungsart. Begründe, wie unklare Fälle trotz einer schnellen Sammelfreigabe sichtbar bleiben.
- UI-Design · 4 Minuten: Gestalte Vorher/Nachher, Mehrfachauswahl und die endgültige Freigabe. Beispiel: „Landingpage fertigstellen“ wechselt vom 23. auf den 22.10., zuständig bleibt Anna. Eine Auswahl ist noch keine Ausführung.
- Fehlerfälle · 2 Minuten: Definiere den Ablauf, wenn eine andere Person während der Prüfung eine Aufgabe ändert oder nur 17 von 20 Änderungen übernommen werden.
Eine Teilübernahme ist nicht immer zulässig. Lege fest, ob Änderungen unabhängig sind oder gemeinsam erfolgreich sein müssen. Zeige neben den erlaubten Aktionen auch, was bewusst noch nicht verändert wird.
04 / EINE MÖGLICHE MUSTERLÖSUNG
Konkrete Änderungen statt pauschaler Sicherheit.
Interaktive Review-Simulation öffnen
Vollständig lokale Designsimulation. Alle 24 Aufgaben, Personen, Regeln und Ergebnisse sind fiktiv. Keine KI, keine Serververbindung und keine Garantie, dass der Gesamtplan bis Freitag aufgeht.
Vorschläge prüfen
20 prüfbar · 4 zu klären · 0 übernommen · 0 abgelehnt
„Prüfbar“ bedeutet nur: Die vereinfachten Regeln des Beispiels sind erfüllt. Es ist keine Konfidenzangabe und keine Garantie für einen fehlerfreien Projektplan.
0 ausgewählt. 4 offene Problemfälle werden nicht mit übernommen. Teilübernahme ist hier eine ausdrückliche Beispielannahme; unabhängige Änderungen sind im Szenario zulässig.
Gesondert klären (4)
API-Abnahme planen
Unklar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Person offen
Die zuständige Person fehlt.
Vorschlag bearbeiten: API-Abnahme planen
Externen Termin klären
Unklar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- Termin offen
Zuständig: Anna
Der mögliche Abschlusstermin ist noch offen.
Vorschlag bearbeiten: Externen Termin klären
Aufwand einschätzen
Unklar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Eine bestätigte Aufwandsschätzung fehlt.
Vorschlag bearbeiten: Aufwand einschätzen
Prototyp testen
Konflikt- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ben ist am 22.10. bereits für eine andere Aufgabe eingeplant.
Vorschlag bearbeiten: Prototyp testen
Alle 24 Vorschläge und ihre Einzelentscheidungen ansehen
Landingpage fertigstellen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Landingpage fertigstellen
Navigation testen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Navigation testen
Iconset prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Iconset prüfen
Formulartexte abstimmen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Formulartexte abstimmen
Design-Tokens dokumentieren
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Design-Tokens dokumentieren
Mobile Ansicht prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Mobile Ansicht prüfen
Kontrastwerte prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Kontrastwerte prüfen
Komponenten abstimmen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Komponenten abstimmen
Suchzustände gestalten
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Suchzustände gestalten
Onboarding skizzieren
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Onboarding skizzieren
Fehlertexte ergänzen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Fehlertexte ergänzen
Tastaturbedienung prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Tastaturbedienung prüfen
Abstände überarbeiten
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Abstände überarbeiten
Tabellenzustände prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Tabellenzustände prüfen
Filterlogik prüfen
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Filterlogik prüfen
Exportansicht gestalten
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Exportansicht gestalten
Hilfetexte schreiben
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Hilfetexte schreiben
Review vorbereiten
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Cem - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Cem
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Review vorbereiten
Abnahme dokumentieren
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Anna - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Anna
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Abnahme dokumentieren
Übergabe vorbereiten
Prüfbar- Aktueller Stand · Version 1
- 23.10.2026
Zuständig: Ben - Vorschlag · geprüft mit Version 1
- 22.10.2026
Zuständig: Ben
Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft.
Vorschlag bearbeiten: Übergabe vorbereiten
Offene Problemfälle stehen bereits im Bereich darüber. Zusammen bleiben alle 24 Vorschläge erreichbar.
Ergebnis je Änderung
Noch kein Ausführungsergebnis.
Probiere diese Abläufe aus
- Wähle die 20 prüfbaren Vorschläge gemeinsam aus. Die vier offenen Problemfälle bleiben separat sichtbar. Öffne die Einzelansicht, um Termine, Zuständigkeiten und Begründungen zu prüfen.
- Öffne die Freigabe. Sie zeigt genau die ausgewählten Änderungen. Abbrechen und Escape erhalten die Auswahl und führen nichts aus.
- Simuliere die drei Fehlschläge: 17 von 20 werden übernommen. Wähle anschließend die drei noch prüfbaren Änderungen erneut aus und nutze für den nächsten Durchlauf das erfolgreiche Ergebnis. Die bereits übernommenen Einträge werden nicht erneut ausgewählt.
- Setze das Beispiel zurück und simuliere eine zwischenzeitliche Änderung. Ein Vorschlag bleibt wegen eines Versionskonflikts unangetastet; die übrigen zulässigen Änderungen werden übernommen.
- Bearbeite einen unklaren Fall oder den Konflikt. Ergänze im Beispiel Termin und Person und bestätige die Prüfung. Beim Ressourcenkonflikt ist Ben am 22.10. belegt: Wähle einen anderen Termin oder eine andere Person.
- Nach einer Bearbeitung musst du den Vorschlag neu auswählen. Du kannst einzelne Vorschläge auch ablehnen. Zum Wiederholen aller Ausgangsfälle dient „Lernbeispiel zurücksetzen“.
Warum diese Entscheidungen?
- Problemfälle zuerst: Unklare Angaben und Konflikte stehen direkt in der Oberfläche. Die große Gruppe bleibt einzeln überprüfbar, ohne die vier offenen Fälle zu verdrängen.
- Auswahl ist keine Zustimmung zur Ausführung: Erst ein eigener Freigabedialog zeigt die endgültigen Termine und Personen. Änderungen am Vorschlag entfernen dessen Auswahl. Die Freigabe enthält einen konkreten Snapshot und keine veränderliche allgemeine Zusage. Der Fokus beginnt an der Überschrift, damit die lange Änderungsliste von oben geprüft werden kann.
- Erneute Prüfung: Vor der simulierten Ausführung werden Version, Vorschlagsrevision und freigegebene Werte verglichen. Ein abweichender Stand wird nicht still überschrieben.
- Ergebnisse pro Aufgabe: Nach Teilfehlern bleiben übernommene Einträge gesperrt. Bestätigt fehlgeschlagene Änderungen können neu geprüft und freigegeben werden. Ein Versionskonflikt verlangt eine erneute Prüfung des aktuellen Stands.
- Einfaches, sichtbares Modell: Alle 24 Vorschläge bleiben über Problemfälle und Einzelansicht erreichbar. Es gibt keine echte Ressourcenoptimierung; die Prüfregeln sind bewusst begrenzt.
Der Nachteil: Die zusätzlichen Prüf- und Freigabeschritte kosten Zeit. Für die riskanteren Änderungen dieses Szenarios ist das eine begründete Ausgangshypothese. In einem echten Produkt müsste geprüft werden, ob Menschen die Folgen verstehen und die Sammelfreigabe angemessen verwenden.
Die Simulation wartet 600 ms und zeigt danach das konstruierte Ergebnis. Nach dem Start wird nicht mehr abgebrochen. Es gibt kein Produkt-Undo; Zurücksetzen startet lediglich die Übung neu. Ein reales System braucht serverseitige Validierung, Berechtigungen, Schutz vor doppelten Aufträgen und einen verlässlichen Umgang mit unbekannten Ergebnissen. Ein Timeout allein rechtfertigt keinen unkontrollierten Wiederholungsversuch.
React-Code, CSS und Review-Modell ansehen
Dies ist der tatsächliche Code der Strategien und Review-Simulation. Beispieldaten und Prüfregeln stehen im Modell. Zum Übernehmen werden React und angepasste Importpfade benötigt.
coaching-agent-review.tsx
"use client";
import { useEffect, useId, useRef, useState, type FormEvent } from "react";
import { applyReviewBatch, canApplyReview, editReviewSuggestion, initialReviewSuggestions, reviewOwners, snapshotReview, type ReviewResult, type ReviewScenario, type ReviewSnapshot, type ReviewSuggestion } from "@/lib/coaching-agent-review";
import "./coaching-agent-review.css";
const showDate = (value: string) => value ? value.split("-").reverse().join(".") : "Termin offen";
const statuses = { ready: "Prüfbar", unclear: "Unklar", conflict: "Konflikt", applied: "Übernommen", failed: "Fehlgeschlagen", rejected: "Abgelehnt" };
const strategies = {
autopilot: { label: "Autopilot", text: "Ausführung innerhalb vorab festgelegter Regeln. Dafür müssten Auftrag, Grenzen und Stop-Bedingungen bereits vereinbart sein. Diese Strategieansicht führt nichts aus." },
review: { label: "Review", text: "Vorschläge vergleichen, Problemfälle klären und eine konkrete Auswahl freigeben. Das ist der Ausgangspunkt für diese Übung; bisher wurde nichts ausgeführt." },
manual: { label: "Manuell", text: "Jede Änderung selbst bearbeiten. Mehr Einzelarbeit, dafür direkte Kontrolle über jede Entscheidung. Auch dieser Strategiewechsel verändert keine Aufgaben." },
};
export function CoachingAgentStrategies() {
const [strategy, setStrategy] = useState<keyof typeof strategies>("review");
return <div className="agent-strategy"><div className="agent-buttons" role="group" aria-label="Workflow-Strategie vergleichen">{Object.entries(strategies).map(([key, value]) => <button type="button" key={key} aria-pressed={strategy === key} onClick={() => setStrategy(key as keyof typeof strategies)}>{value.label}</button>)}</div><h3>Projektplanung optimieren</h3><p>24 Aufgaben im fiktiven Szenario: <strong>20 prüfbar · 3 unklar · 1 Konflikt.</strong></p><p>{strategies[strategy].text}</p><p className="agent-note">Designvergleich, keine Modusumschaltung eines echten Agenten. Die bedienbare Review-Ansicht folgt in der Musterlösung.</p></div>;
}
function EditProposal({ item, onSave, disabled }: { item: ReviewSuggestion; onSave: (date: string, owner: string, clarified: boolean) => void; disabled: boolean }) {
const [date, setDate] = useState(item.date);
const [owner, setOwner] = useState(item.owner);
const [clarified, setClarified] = useState(false);
const [error, setError] = useState("");
function submit(event: FormEvent) {
event.preventDefault();
if (!clarified) { setError("Bestätige, dass du aktuellen Stand und offene Angaben im Beispiel geprüft hast."); return; }
onSave(date, owner, clarified);
}
return <details className="agent-edit"><summary>Vorschlag bearbeiten: {item.title}</summary><form onSubmit={submit}><label>Neuer Termin<input type="date" required min="2026-10-19" max="2026-10-23" value={date} disabled={disabled} onChange={event => setDate(event.target.value)} /></label><label>Zuständig<select required value={owner} disabled={disabled} onChange={event => setOwner(event.target.value)}><option value="">Bitte wählen</option>{reviewOwners.map(value => <option key={value}>{value}</option>)}</select></label><label className="agent-check"><input type="checkbox" checked={clarified} disabled={disabled} onChange={event => { setClarified(event.target.checked); setError(""); }} /> Aktuellen Stand und offene Angaben im Beispiel geprüft</label>{error && <p role="alert" className="agent-error">{error}</p>}<button type="submit" disabled={disabled}>Bearbeitung prüfen</button></form></details>;
}
export function CoachingAgentReview() {
const [items, setItems] = useState(initialReviewSuggestions);
const [selected, setSelected] = useState<string[]>([]);
const [scenario, setScenario] = useState<ReviewScenario>("success");
const [snapshot, setSnapshot] = useState<ReviewSnapshot[]>([]);
const [results, setResults] = useState<ReviewResult[]>([]);
const [pending, setPending] = useState(false);
const busy = useRef(false);
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
const dialog = useRef<HTMLDialogElement>(null);
const confirmHeading = useRef<HTMLHeadingElement>(null);
const resultHeading = useRef<HTMLHeadingElement>(null);
const reviewHeading = useRef<HTMLHeadingElement>(null);
const focusAfter = useRef<HTMLElement | null>(null);
const [message, setMessage] = useState("Noch keine Änderungen übernommen.");
const id = useId();
const ready = items.filter(canApplyReview);
const problems = items.filter(item => item.status === "unclear" || item.status === "conflict");
const eligibleSelected = snapshotReview(items, selected);
useEffect(() => () => { if (timer.current !== null) clearTimeout(timer.current); }, []);
useEffect(() => { if (!pending && focusAfter.current) { focusAfter.current.focus(); focusAfter.current = null; } }, [pending]);
function toggle(itemId: string) { setSelected(previous => previous.includes(itemId) ? previous.filter(value => value !== itemId) : [...previous, itemId]); }
function edit(item: ReviewSuggestion, date: string, owner: string, clarified: boolean) {
setItems(previous => previous.map(value => value.id === item.id ? editReviewSuggestion(value, date, owner, clarified) : value));
setSelected(previous => previous.filter(value => value !== item.id)); setMessage("Vorschlag erneut geprüft. Eine Bearbeitung entfernt seine bisherige Auswahl; bitte erneut auswählen und freigeben."); reviewHeading.current?.focus();
}
function confirm() { setSnapshot(eligibleSelected); dialog.current?.showModal(); confirmHeading.current?.focus(); }
function apply() {
if (busy.current || snapshot.length === 0) return;
busy.current = true; setPending(true);
timer.current = setTimeout(() => {
timer.current = null;
const batch = applyReviewBatch(items, snapshot, scenario);
setItems(batch.items); setResults(batch.results); setSelected([]); setSnapshot([]);
setMessage(`${batch.results.filter(result => result.outcome === "applied").length} von ${batch.results.length} freigegebenen Änderungen lokal übernommen. Ergebnis je Aufgabe prüfen.`);
dialog.current?.close(); focusAfter.current = resultHeading.current; busy.current = false; setPending(false);
}, 600);
}
function card(item: ReviewSuggestion) {
const eligible = canApplyReview(item);
return <li key={`${item.id}-${item.revision}`} className="agent-change"><div className="agent-change-header"><h4>{item.title}</h4><span className={`agent-badge status-${item.status}`}>{statuses[item.status]}</span></div><dl className="agent-diff"><div><dt>Aktueller Stand · Version {item.serverVersion}</dt><dd>{showDate(item.currentDate)}<br />Zuständig: {item.currentOwner}</dd></div><div><dt>Vorschlag · geprüft mit Version {item.baseVersion}</dt><dd>{showDate(item.date)}<br />Zuständig: {item.owner || "Person offen"}</dd></div></dl><p className="agent-reason">{item.reason}</p>{eligible && <label className="agent-check"><input type="checkbox" disabled={pending} checked={selected.includes(item.id)} onChange={() => toggle(item.id)} /> {item.title} auswählen</label>}{!["applied", "rejected"].includes(item.status) && <><EditProposal key={`${item.id}-${item.revision}`} item={item} disabled={pending} onSave={(date, owner, clarified) => edit(item, date, owner, clarified)} /><button type="button" disabled={pending} className="agent-reject" aria-label={`${item.title} ablehnen`} onClick={() => { setItems(previous => previous.map(value => value.id === item.id ? { ...value, status: "rejected" } : value)); setSelected(previous => previous.filter(value => value !== item.id)); setMessage(`„${item.title}“ abgelehnt. Keine Aufgabenänderung ausgeführt.`); reviewHeading.current?.focus(); }}>Ablehnen</button></>}</li>;
}
return <div className="agent-review">
<p className="agent-note">Vollständig lokale Designsimulation. Alle 24 Aufgaben, Personen, Regeln und Ergebnisse sind fiktiv. Keine KI, keine Serververbindung und keine Garantie, dass der Gesamtplan bis Freitag aufgeht.</p>
<h3 ref={reviewHeading} tabIndex={-1}>Vorschläge prüfen</h3><p className="agent-summary">{ready.length} prüfbar · {problems.length} zu klären · {items.filter(item => item.status === "applied").length} übernommen · {items.filter(item => item.status === "rejected").length} abgelehnt</p>
<p className="agent-note">„Prüfbar“ bedeutet nur: Die vereinfachten Regeln des Beispiels sind erfüllt. Es ist keine Konfidenzangabe und keine Garantie für einen fehlerfreien Projektplan.</p>
<div className="agent-selection"><button type="button" disabled={pending || ready.length === 0} onClick={() => setSelected(ready.map(item => item.id))}>Alle {ready.length} prüfbaren Vorschläge auswählen</button><button type="button" disabled={pending || selected.length === 0} onClick={() => setSelected([])}>Auswahl leeren</button></div>
<label className="agent-scenario" htmlFor={`${id}-scenario`}>Ergebnis der nächsten Ausführung simulieren</label><select id={`${id}-scenario`} value={scenario} disabled={pending} onChange={event => setScenario(event.target.value as ReviewScenario)}><option value="success">Alle erfolgreich</option><option value="partial">Letzte 3 schlagen fehl</option><option value="concurrent">Ein Versionskonflikt</option></select>
<p className="agent-notice">{eligibleSelected.length} ausgewählt. {problems.length} offene Problemfälle werden nicht mit übernommen. Teilübernahme ist hier eine ausdrückliche Beispielannahme; unabhängige Änderungen sind im Szenario zulässig.</p><button className="agent-primary" type="button" disabled={pending || eligibleSelected.length === 0} onClick={confirm}>{eligibleSelected.length} Änderungen zur Freigabe prüfen</button><p role="status" aria-atomic="true" className="agent-message">{message}</p>
<section className="agent-problems" aria-label="Offene Problemfälle"><h4>Gesondert klären ({problems.length})</h4>{problems.length ? <ul className="agent-changes">{problems.map(card)}</ul> : <p>Keine offenen Unklarheiten oder Konflikte im Beispiel.</p>}</section>
<details className="agent-list"><summary>Alle 24 Vorschläge und ihre Einzelentscheidungen ansehen</summary><ul className="agent-changes">{items.filter(item => item.status !== "unclear" && item.status !== "conflict").map(card)}</ul><p className="agent-note">Offene Problemfälle stehen bereits im Bereich darüber. Zusammen bleiben alle 24 Vorschläge erreichbar.</p></details>
<section className="agent-results" aria-label="Ausführungsergebnis"><h3 ref={resultHeading} tabIndex={-1}>Ergebnis je Änderung</h3>{results.length ? <><ul>{results.map(result => <li key={result.id}><strong>{result.title} · {result.outcome === "applied" ? "Übernommen" : result.outcome === "failed" ? "Fehlgeschlagen" : result.outcome === "conflict" ? "Versionskonflikt" : "Nicht ausgeführt"}</strong><p>{result.detail}</p></li>)}</ul><p className="agent-note">Nur die letzte Ausführung ist hier protokolliert. Bereits übernommene Änderungen bleiben in der Einzelansicht als übernommen markiert.</p></> : <p>Noch kein Ausführungsergebnis.</p>}</section>
<button type="button" disabled={pending} onClick={() => { setItems(initialReviewSuggestions()); setSelected([]); setResults([]); setScenario("success"); setMessage("Lernbeispiel zurückgesetzt. Noch keine Änderungen übernommen."); reviewHeading.current?.focus(); }}>Lernbeispiel zurücksetzen</button>
<dialog ref={dialog} className="agent-confirm" aria-labelledby={`${id}-confirm-title`} onCancel={event => { if (busy.current) event.preventDefault(); }}><div><h3 id={`${id}-confirm-title`} ref={confirmHeading} tabIndex={-1}>Diese {snapshot.length} Änderungen freigeben?</h3><p>Nur die unten aufgeführten Termine und Zuständigkeiten werden lokal simuliert übernommen. Die offenen Problemfälle bleiben unberührt. Die Vorschläge werden unmittelbar vor der Ausführung nochmals gegen die Modellversion geprüft.</p><ul>{snapshot.map(change => { const item = items.find(value => value.id === change.id)!; return <li key={change.id}><strong>{item.title}</strong><p>{showDate(item.currentDate)} / {item.currentOwner} → {showDate(change.date)} / {change.owner}</p></li>; })}</ul><p role="status" aria-atomic="true">{pending ? "Ausführung wird lokal simuliert … Abbrechen ist nach dem Start nicht mehr möglich." : "Noch nichts übernommen. Abbrechen oder Escape erhält deine Auswahl."}</p><div className="agent-buttons"><button type="button" disabled={pending} onClick={() => dialog.current?.close()}>Abbrechen</button><button type="button" className="agent-primary" disabled={pending} onClick={apply}>Auswahl jetzt übernehmen (Simulation)</button></div></div></dialog>
</div>;
}
coaching-agent-review.css
.agent-strategy,.agent-review{min-width:0;max-width:100%;border:1px solid #c5d0e3;border-radius:12px;background:#f3f6fc;padding:24px;margin-top:24px}
.agent-buttons,.agent-selection{display:flex;flex-wrap:wrap;gap:10px}
.agent-strategy button,.agent-review button,.agent-confirm button{min-height:44px;padding:10px 14px;border:1px solid #748198;border-radius:7px;font-size:13px;line-height:1.7;background:white;color:#233753;max-width:100%;overflow-wrap:anywhere}
.agent-strategy button[aria-pressed=true],.agent-review button.agent-primary,.agent-confirm button.agent-primary{background:#2558ed;color:white;border-color:#2558ed}
.agent-review button:disabled,.agent-confirm button:disabled{opacity:.55;cursor:not-allowed}
.lesson-content .agent-strategy h3,.lesson-content .agent-review h3{font:500 24px/1.5 system-ui,sans-serif;margin:20px 0 12px;overflow-wrap:anywhere;scroll-margin-top:110px}
.lesson-content .agent-strategy p,.lesson-content .agent-review p{font-size:14px;line-height:1.8;margin-top:12px;overflow-wrap:anywhere}
.lesson-content .agent-note,.agent-confirm p{font-size:12px;line-height:1.8;color:#536174;margin-top:12px}
.agent-summary{font-weight:600;color:#23447d}
.agent-selection{margin-top:20px}
.agent-scenario{display:block;font-size:13px;line-height:1.8;margin:24px 0 8px;font-weight:500}
.agent-review>select,.agent-edit select,.agent-edit input[type=date]{display:block;width:100%;max-width:100%;min-width:0;min-height:44px;padding:10px 8px;background:white;color:#233753;border:1px solid #748198;border-radius:6px;font-size:13px;line-height:1.7}
.agent-review>select{max-width:500px}
.agent-notice{padding:16px;border-left:3px solid #b07821;background:#fff3d9;color:#72501a;margin-bottom:16px}
.agent-message{color:#254c8a}
.agent-problems{margin-top:24px;padding-top:20px;border-top:1px solid #c5d0e3}
.lesson-content .agent-problems>h4{font-size:18px;font-weight:600;line-height:1.7;margin:0}
.agent-changes{list-style:none;margin:16px 0 0;padding:0}
.agent-change{background:white;border:1px solid #c4cfe2;border-radius:9px;padding:20px;margin-top:14px;min-width:0}
.agent-change-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap}
.lesson-content .agent-change h4{font:600 17px/1.6 system-ui,sans-serif;margin:0;overflow-wrap:anywhere;flex:1 1 180px}
.agent-badge{font-size:11px;line-height:1.8;border-radius:5px;padding:3px 8px;border:1px solid #aebfe0;color:#294c8a;background:#eaf0ff}
.agent-badge.status-unclear,.agent-badge.status-conflict,.agent-badge.status-failed{background:#fff0d5;color:#795012;border-color:#d0ac68}
.agent-badge.status-applied{background:#e4f2ed;color:#215a46;border-color:#a4c8b9}
.agent-badge.status-rejected{background:#edf0f5;color:#526078;border-color:#bbc5d5}
.agent-diff{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin:18px 0 0}
.agent-diff>div{border-left:2px solid #c8d4e9;padding-left:12px;min-width:0}
.agent-diff dt{font-size:11px;line-height:1.8;color:#536174}
.agent-diff dd{font-size:14px;line-height:1.8;margin-top:6px;overflow-wrap:anywhere}
.lesson-content .agent-reason{font-size:12px;line-height:1.8;color:#536174;margin-top:16px}
.agent-check{display:flex;align-items:flex-start;gap:12px;font-size:13px;line-height:1.8;min-height:44px;padding:12px 0;cursor:pointer;overflow-wrap:anywhere}
.agent-check input{width:18px;height:18px;flex-shrink:0;accent-color:#2558ed;margin-top:3px}
.agent-edit{border-top:1px solid #d0d9e8;margin-top:12px;padding-top:8px}
.agent-edit summary,.agent-list>summary{font-size:13px;font-weight:500;line-height:1.8;cursor:pointer;min-height:44px;padding:12px 0;overflow-wrap:anywhere}
.agent-edit form>label:not(.agent-check){display:block;font-size:12px;line-height:1.8;margin:12px 0}
.agent-edit form>label>select,.agent-edit form>label>input[type=date]{margin-top:6px}
.agent-review button.agent-reject{margin-top:12px;background:transparent;border:0;text-decoration:underline;text-underline-offset:4px;padding-left:0}
.agent-list{margin-top:24px;border-top:1px solid #c5d0e3;padding-top:12px}
.agent-results{border-top:1px solid #c5d0e3;margin-top:24px;padding:12px 0 24px}
.agent-results ul,.agent-confirm ul{list-style:none;padding:0;margin:16px 0}
.agent-results li,.agent-confirm li{padding:14px 0;border-top:1px solid #d0d9e8;font-size:13px;line-height:1.8;overflow-wrap:anywhere}
.lesson-content .agent-results li p{font-size:12px;line-height:1.8;margin-top:6px;color:#536174}
.lesson-content .agent-error{font-size:13px;line-height:1.8;color:#973b21}
.agent-confirm{position:fixed;inset:0;margin:auto;width:600px;max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);border:1px solid #aabbd5;border-radius:14px;background:white;color:#172131;padding:0;overflow:auto;overscroll-behavior:contain}
.agent-confirm::backdrop{background:#101a30a6}
.agent-confirm>div{padding:24px}
.agent-confirm h3{font:500 24px/1.5 system-ui,sans-serif;margin:0;overflow-wrap:anywhere}
.agent-confirm .agent-buttons{margin-top:24px}
.agent-confirm .agent-buttons button{flex:1 1 180px}
.agent-strategy button:focus-visible,.agent-review :is(button,input,select,summary,h3):focus-visible,.agent-confirm :is(button,h3):focus-visible{outline:3px solid #2558ed;outline-offset:3px}
@media(max-width:640px){.agent-strategy,.agent-review,.agent-confirm>div{padding:18px}.agent-change{padding:16px}.agent-diff{grid-template-columns:1fr;gap:14px}.agent-review>select{font-size:12px}.agent-change-header{gap:10px}}
coaching-agent-review.ts
export type ReviewStatus = "ready" | "unclear" | "conflict" | "applied" | "failed" | "rejected";
export type ReviewSuggestion = {
id: string; title: string; currentDate: string; currentOwner: string; date: string; owner: string;
baseVersion: number; serverVersion: number; revision: number; status: ReviewStatus;
kind: "normal" | "missing" | "resource"; clarified: boolean; reason: string;
};
export type ReviewSnapshot = Pick<ReviewSuggestion, "id" | "date" | "owner" | "baseVersion" | "revision">;
export type ReviewScenario = "success" | "partial" | "concurrent";
export type ReviewResult = { id: string; title: string; outcome: "applied" | "failed" | "conflict" | "blocked"; detail: string };
export const reviewOwners = ["Anna", "Ben", "Cem"] as const;
const titles = ["Landingpage fertigstellen", "Navigation testen", "Iconset prüfen", "Formulartexte abstimmen", "Design-Tokens dokumentieren", "Mobile Ansicht prüfen", "Kontrastwerte prüfen", "Komponenten abstimmen", "Suchzustände gestalten", "Onboarding skizzieren", "Fehlertexte ergänzen", "Tastaturbedienung prüfen", "Abstände überarbeiten", "Tabellenzustände prüfen", "Filterlogik prüfen", "Exportansicht gestalten", "Hilfetexte schreiben", "Review vorbereiten", "Abnahme dokumentieren", "Übergabe vorbereiten", "API-Abnahme planen", "Externen Termin klären", "Aufwand einschätzen", "Prototyp testen"];
export function initialReviewSuggestions(): ReviewSuggestion[] {
return titles.map((title, index) => ({
id: `change-${index + 1}`, title, currentDate: "2026-10-23", currentOwner: reviewOwners[index % 3],
date: index === 21 ? "" : "2026-10-22", owner: index === 20 ? "" : index === 23 ? "Ben" : reviewOwners[index % 3],
baseVersion: 1, serverVersion: 1, revision: 1,
status: index < 20 ? "ready" : index < 23 ? "unclear" : "conflict",
kind: index < 20 ? "normal" : index < 23 ? "missing" : "resource", clarified: index < 20,
reason: index < 20 ? "Ein früherer Abschluss schafft einen Tag Puffer vor der Abnahme am Freitag, 23.10.2026. Abhängigkeiten und Aufwand gelten im Szenario als geprüft." : index === 20 ? "Die zuständige Person fehlt." : index === 21 ? "Der mögliche Abschlusstermin ist noch offen." : index === 22 ? "Eine bestätigte Aufwandsschätzung fehlt." : "Ben ist am 22.10. bereits für eine andere Aufgabe eingeplant.",
}));
}
export function reviewProblem(item: ReviewSuggestion): string {
if (item.baseVersion !== item.serverVersion) return "Der Aufgabenstand wurde zwischenzeitlich geändert. Aktuellen Stand erneut prüfen.";
if (!/^2026-10-(19|20|21|22|23)$/.test(item.date) || !reviewOwners.some(owner => owner === item.owner)) return "Termin zwischen 19. und 23.10. sowie eine zuständige Person angeben.";
if (item.kind === "missing" && !item.clarified) return "Die fehlende Information muss zuerst geklärt werden.";
if (item.kind === "resource" && item.owner === "Ben" && item.date === "2026-10-22") return "Ben ist am 22.10. bereits belegt. Termin oder Zuständigkeit ändern.";
return "";
}
export function canApplyReview(item: ReviewSuggestion): boolean { return (item.status === "ready" || item.status === "failed") && !reviewProblem(item); }
export function editReviewSuggestion(item: ReviewSuggestion, date: string, owner: string, clarified: boolean): ReviewSuggestion {
if (item.status === "applied") return item;
const next = { ...item, date, owner, clarified, baseVersion: item.serverVersion, revision: item.revision + 1 };
const problem = reviewProblem(next);
return { ...next, status: problem ? item.kind === "resource" ? "conflict" : "unclear" : "ready", reason: problem || "Manuell bearbeitet und für das fiktive Szenario erneut geprüft. Auswahl und Freigabe sind weiterhin erforderlich." };
}
export function snapshotReview(items: ReviewSuggestion[], ids: string[]): ReviewSnapshot[] {
return items.filter(item => ids.includes(item.id) && canApplyReview(item)).map(({ id, date, owner, baseVersion, revision }) => ({ id, date, owner, baseVersion, revision }));
}
export function applyReviewBatch(items: ReviewSuggestion[], snapshots: ReviewSnapshot[], scenario: ReviewScenario) {
let next = items.map(item => ({ ...item }));
const unique = snapshots.filter((snapshot, index) => snapshots.findIndex(other => other.id === snapshot.id) === index);
if (scenario === "concurrent" && unique.length) next = next.map(item => item.id === unique[0].id ? { ...item, serverVersion: item.serverVersion + 1, currentDate: "2026-10-26" } : item);
const results: ReviewResult[] = unique.map((snapshot, index) => {
const item = next.find(value => value.id === snapshot.id);
const title = item?.title ?? "Unbekannte Aufgabe";
const result = (outcome: ReviewResult["outcome"], detail: string) => ({ id: snapshot.id, title, outcome, detail });
if (!item || !["ready", "failed"].includes(item.status)) return result("blocked", "Nicht ausführbar; keine Änderung übernommen.");
if (item.serverVersion !== snapshot.baseVersion) {
item.status = "conflict"; item.reason = "Versionskonflikt: Der aktuelle Termin wurde im Test auf 26.10. geändert. Vor erneutem Freigeben prüfen.";
return result("conflict", item.reason);
}
if (item.revision !== snapshot.revision || item.date !== snapshot.date || item.owner !== snapshot.owner || reviewProblem(item)) return result("blocked", "Der Vorschlag entspricht nicht mehr der Freigabe. Erneut prüfen und auswählen.");
if (scenario === "partial" && index >= Math.max(0, unique.length - 3)) {
item.status = "failed"; item.reason = "Bestätigter simulierter Fehlschlag: nichts übernommen. Erneute Freigabe ist möglich.";
return result("failed", item.reason);
}
item.currentDate = snapshot.date; item.currentOwner = snapshot.owner; item.serverVersion++; item.baseVersion = item.serverVersion; item.status = "applied";
return result("applied", "Termin und Zuständigkeit wie freigegeben übernommen (lokale Simulation).");
});
return { items: next, results };
}
05 / REFLEXION · 3 MINUTEN
Vertrauen braucht einen prüfbaren Bezug.
Würdest du überall „92 % Konfidenz“ anzeigen?
Was müsste diese Zahl bedeuten, damit sie für eine Entscheidung hilfreich ist? Welche Informationen wären sonst wichtiger?
Mögliche Antwort zu Konfidenzangaben
Ich würde zuerst klären, worauf sich die Zahl bezieht und wie sie ermittelt sowie überprüft wurde. Eine Modellbewertung ist nicht automatisch die Wahrscheinlichkeit, dass ein Terminplan in der realen Welt gelingt. Ohne verständlichen Bezug und geeignete Evaluation könnte eine präzise Prozentangabe falsche Sicherheit vermitteln.
In diesem Beispiel sind fehlende Aufwandsschätzung, belegte Person, Aufgabenstand und Begründung direkt handlungsrelevant. Die Musterlösung zeigt diese Informationen statt einer erfundenen Konfidenzzahl. Ob eine zusätzliche Unsicherheitsanzeige Menschen bei der Entscheidung hilft, müsste im Nutzungskontext geprüft werden.
Dürfen die 20 prüfbaren Änderungen schon übernommen werden?
Würdest du alles blockieren, eine Teilübernahme erlauben oder eine ausdrückliche Wahl anbieten? Berücksichtige Abhängigkeiten und mögliche Auswirkungen auf die vier offenen Fälle.
Mögliche Antwort zur Teilübernahme
Wenn die Änderungen unabhängig sind und eine Teilübernahme das Projekt nicht inkonsistent macht, würde ich eine klar begrenzte Freigabe der 20 zulässigen Einträge anbieten. Die vier offenen Fälle und ihre Folgen bleiben sichtbar. Der Button benennt die Auswahl und verspricht nicht, das ganze Projekt fertigzuplanen.
Wenn die Termine voneinander abhängen oder alle Änderungen zusammen gelten müssen, würde ich die gemeinsame Ausführung bis zur Klärung blockieren oder einen getrennten Entwurf ermöglichen. Die richtige Entscheidung folgt aus den fachlichen Regeln; sie darf nicht allein aus dem Wunsch nach einem schnell bedienbaren Button entstehen.
06 / FACHLICH VERTIEFEN
Kontrolle und angemessenes Vertrauen zusammen gestalten.
Das People + AI Guidebook behandelt Erklärbarkeit, Modellkonfidenz und angemessenes Vertrauen sowie Feedback und Kontrolle. Es liefert keine pauschale Empfehlung, jede KI-Ausgabe mit einer Prozentzahl zu versehen. Google PAIR: Explainability + Trust, Feedback + Control.
Das zugehörige Codelab bietet Übungen zur Entwicklung vertrauenswürdiger KI-Produkte mit dem Guidebook. Nutze es als Vertiefung für Nutzerbedürfnisse, Erklärbarkeit und die Balance zwischen Kontrolle und Automatisierung. Google: Building Trusted AI Products.
Die praktische Konsequenz für diese Lektion ist eine eigene Gestaltungsentscheidung: Vertrauen entsteht hier durch prüfbare Änderungen, sichtbare Grenzen und Korrekturmöglichkeiten. Selbstbewusst formulierte KI-Ausgaben allein reichen dafür nicht.
DEIN MERKSATZ
Automatisiere die Arbeit, nicht die Verantwortung.
Ein gutes KI-Interface macht einfache Entscheidungen schnell und schwierige Entscheidungen bewusst.