feat(startseite): Giorgio entfernt, Belegschaft auf die fünf Agenten

Auf ausdrücklichen Wunsch: Giorgio entfällt vollständig. Das weicht bewusst
von §6 des Auftrags ab, der ihn als Personalverwalter und Vorgesetzten
vorsah — festgehalten, damit die Abweichung später nachvollziehbar bleibt.

Entfernt: Rollendefinition `AGENT_SUPERVISOR`, sein gezeichnetes Porträt, sein
Eintrag in der Auslastung und in der Belegschaftsansicht sowie die Erwähnung
in der Produkttour. Die Personalverwaltung bleibt unverändert über den
Menüpunkt «Meine Agenten» erreichbar — sie brauchte nie eine eigene Person am
Bildschirm.

Mit Giorgio entfällt auch die einzige Kennzahl, die aus den Freigabevorgängen
kam; `computeAgentWorkload` braucht `agentWorkItems` deshalb nicht mehr.

Ordner und Komponenten heissen jetzt nach ihrem Inhalt: `components/staff/`,
`AgentStaffOverview`, `StaffBackdrop`. «Meetingraum» war seit dem Umbau auf
Personenkarten irreführend, und ein falscher Name kostet den Nächsten mehr
Zeit als die Umbenennung.

Fünf statt sechs Karten heisst Flexlayout statt Dreierraster: drei oben, zwei
mittig darunter, gleich breit und ohne Lücke. Die Karten geben ihre Höhe nicht
mehr selbst vor — mit `height: 100%` beanspruchte jede die volle Fläche und
die zweite Zeile fiel aus dem sichtbaren Bereich.

Geprüft: 433 Tests, Typecheck, Build, ESLint, Token-Schwelle (889/925).
Browser 1280–1920 px und Tablet: fünf Karten vollständig sichtbar, keine
Überlappung, Titel und «Filter & Übersicht» beim Einstieg sichtbar, alle fünf
Klicks auf der richtigen Subpage, «Meine Agenten» weiterhin erreichbar, keine
Konsolenfehler, keine 404.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-08-06 15:03:18 +02:00
parent 435f2aa2f1
commit 093a958dcf
19 changed files with 56 additions and 184 deletions
+5 -13
View File
@@ -3,7 +3,7 @@ import type { AgentWorkload } from '../domain/agentWorkload'
import type { AgentProtocolEntry } from '../domain/agentProtocol'
import type { TeamAgent } from '../domain/teamAgent'
import { AgentStatus } from '../domain/teamAgent'
import { AGENT_SUPERVISOR, AGENT_WORKSPACES } from '../lib/agentWorkspaces'
import { AGENT_WORKSPACES } from '../lib/agentWorkspaces'
import { AGENT_AUTONOMY_LABELS } from '../lib/constants'
/**
@@ -13,10 +13,6 @@ import { AGENT_AUTONOMY_LABELS } from '../lib/constants'
* als «letzte Handlung» gilt und wie eine Zeitangabe in Alltagssprache lautet,
* sind fachliche Festlegungen. Der Stichzeitpunkt ist ein Parameter — dieselbe
* Datenlage ergibt damit immer dasselbe Ergebnis und lässt sich prüfen.
*
* Giorgio steht bewusst am Ende: er ist Vorgesetzter, kein sechster
* Sachbearbeiter, und sein Klick führt nicht auf eine Arbeitsseite, sondern in
* die Personalverwaltung.
*/
const MINUTE = 60 * 1000
@@ -73,7 +69,7 @@ export function buildAgentPresence(
}
const byId = new Map(agents.map(a => [a.id, a]))
const roster = [...AGENT_WORKSPACES, AGENT_SUPERVISOR]
const roster = AGENT_WORKSPACES
return roster.map(member => {
const dossier = byId.get(member.id)
@@ -83,17 +79,13 @@ export function buildAgentPresence(
agentId: member.id,
name: member.name,
role: member.role,
// Personalblatt zuerst; für Giorgio, der keines hat, die Angaben aus
// der zentralen Rollendefinition.
department: dossier?.department ?? member.department ?? '',
personnelNumber: dossier?.personnelNumber ?? member.personnelNumber ?? '',
department: dossier?.department ?? '',
personnelNumber: dossier?.personnelNumber ?? '',
path: member.path,
// Ohne Personalblatt gilt jemand als im Dienst: die Belegschaftsansicht
// soll niemanden fälschlich als pausiert zeigen, nur weil ein Dossier fehlt.
onDuty: dossier ? dossier.status === AgentStatus.ACTIVE : true,
// Giorgio führt die Belegschaft und entscheidet nichts allein über
// Objekte — seine Stufe ergibt sich aus der Rolle, nicht aus einem Dossier.
autonomy: dossier ? (AGENT_AUTONOMY_LABELS[dossier.autonomyLevel] ?? '') : 'Vorgesetzter',
autonomy: dossier ? (AGENT_AUTONOMY_LABELS[dossier.autonomyLevel] ?? '') : '',
workload: workload[member.id],
lastAction: action
? { title: action.title, when: formatRelativeTime(action.timestamp, now) }