PRs werden beim Sync als Tickets (is_pull_request) angelegt, mit
Projektfarbe, schwarzen Querstreifen und PR-Nummer; im Spalten-Modal
mit Link auf den PR.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Die Spalten-Ansicht selbst braucht weiterhin "aeltestes zuerst" fuer
die Board-Regel (aelteste 4 einzeln, Rest als Stapel, F3), daher wird
die Liste nur fuer die Modal-Ausgabe (Klick auf eine Kanban-Spalte)
umgedreht.
Schließt #102
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Das Event-Modal zeigte bisher die volle vom Server gelieferte Liste
(bis zu 200 Events) ungefiltert an und war dadurch schnell unuebersichtlich.
filterEventsForToday() schraenkt die Anzeige auf Events des aktuellen
Kalendertags (lokale Zeitzone, wie formatEventTime()) ein.
Schliesst #100
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bisher meldeten Agenten walking_to_board/interacting_with_board fuer
Ticket-Uebernahmen faktisch nie, wodurch das Ticket ohne sichtbaren
Board-Besuch die Spalte wechselte. office-render.js taktet den Besuch
jetzt selbst (analog zu PO-/Tuerbesuchen): der zustaendige Agent laeuft
vom eigenen (dann leeren) Schreibtisch zum Board, verschiebt dort
sichtbar das Ticket und laeuft zurueck. Eine echte Meldung des Agenten
(walking_to_board/interacting_with_board) hat weiterhin Vorrang und
unterdrueckt den selbst getakteten Besuch.
Schliesst #76
Wer einen Server aus der Ping-Ueberwachung nehmen wollte, musste sich bisher auf den
Rechner mit check_fds.sh einloggen und die hosts.conf editieren - und die Kachel blieb
danach trotzdem im System-Monitor stehen, weil ein einmal gemeldetes System nirgends
wieder geloescht werden konnte.
Die Liste steht jetzt in der Datenbank und ist ueber ein Zahnrad neben der Ueberschrift
"Systeme" pflegbar, analog zum Zahnrad am PO-Platz (Issue #27). Jeder Host gehoert dem
OPs-Agenten (Issue #66), der ihn anpingt: API und Ping-Check laufen nicht zwangslaeufig
auf demselben Rechner, die API kann die hosts.conf also nicht selbst schreiben.
check_fds.sh holt sie stattdessen bei jedem Lauf mit seinem Agenten-Key ab und schreibt
daraus die lokale Datei; ist die API nicht erreichbar, pingt es unveraendert nach der
zuletzt geschriebenen Liste weiter.
Beim ersten Lauf laedt der Check seine bestehende hosts.conf hoch, damit die bereits
ueberwachten Server nicht von Hand nachgetragen werden muessen. Dass die API das nur
einmal annimmt (Marker in host_config_imports) und "noch nie konfiguriert" per 204 von
"im Frontend geleert" per 200 unterscheidet, ist noetig, damit ein Ping-Rechner mit alter
lokaler Datei die dort geloeschten Hosts nicht wieder anlegt.
Loeschen raeumt mit auf: Ein entfernter Host nimmt seine Kachel mit - beide Ids, denn der
status.txt-Import benennt ihn nach dem Hostnamen, die REST-Meldung nach dessen Slug.
Kacheln ohne zugehoerigen Host (Selbstmelder oder Reste laengst entfernter Hosts) stehen
im selben Dialog unter "Weitere Kacheln im System-Monitor" und sind dort einzeln
loeschbar - dafuer gibt es neu DELETE /api/v1/systems/{id}.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015vNjbfr8M3HSfWMee92GTE
Bislang wurde ein Ticket beim Wechsel von/zu "in_arbeit" sofort an seiner neuen
Spalte gezeichnet, unabhaengig davon, ob der zustaendige Entwickler laut eigenem
gemeldetem state ("walking_to_board") ueberhaupt schon am Board angekommen war -
die Animation wirkte dadurch unvollstaendig/vorgezogen. Analog zu der fuer
Tuer-/PO-Besuche in Issue #55 eingefuehrten Merge-Logik haelt office-render.js
das Ticket nun an seiner alten Stelle, bis der zustaendige Agent laut aktuellstem
Poll das Board erreicht hat (oder nicht mehr feststellbar ist).
detectAgentOwnedTicketChanges() und hasAgentReachedBoard() in office-scene.js
kapseln die dafuer noetige Erkennungs-/Entscheidungslogik pur und testbar.
Die per PING ueberwachten lokalen Server (check_fds.sh -> status.txt ->
LegacyStatusFileReader -> SystemRepository) landen bereits als Kacheln im
System-Monitor, dem mittleren der drei Monitore an der Buero-Wand - das ist
exakt der "alte Monitor" aus dem Issue. GET /api/v1/systems liefert
last_check_at dafuer schon mit, das Klick-Modal hat den Wert aber bisher
weder abgeholt noch angezeigt.
buildSystemModalContent() (office-scene.js) formatiert last_check_at jetzt
ueber die neue formatSystemCheckTime() - sie kommt sowohl mit ISO-8601
(API-gemeldete Systeme) als auch mit dem "YYYY-MM-DD HH:MM"-Format der
Legacy-status.txt klar. renderSystemModalBody() (office-render.js) zeigt den
Zeitpunkt nur bei Status "ok" an ("zuletzt erfolgreich geprüft: ..."), da nur
dann Erreichbarkeit UND Ping-Erfolg zusammenfallen - bei "Fehler" bliebe eine
Zeitangabe ohne Aenderung an check_fds.sh irrefuehrend.
Bewusst nicht Teil dieser Aenderung: Die im Issue zusaetzlich genannte
Portscan-Liste (Detailseite fuer weitere, nur manuell zu pruefende Server)
ist als "koennten" markiert und ohne konkrete Vorgabe zu unscharf fuer eine
automatisierte Umsetzung. Die sechs konkret genannten Hosts/IPs gehoeren in
die lokale, nicht versionierte hosts.conf (Analogon zu credentials.conf) und
damit auf den Produktivserver, nicht in dieses oeffentliche Repo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bisher wurde ein Ticket sofort an seiner neuen Spalte gezeichnet, sobald ein
Statuswechsel erkannt wurde - der Tuerbesuch (Rolle "user") bzw. PO-Besuch
liefen davon unabhaengig erst danach als reine Kosmetik ab. Jetzt haelt
office-render.js das betroffene Ticket an seiner alten Stelle (neue Tickets
bleiben ganz verborgen), bis die zugehoerige Persona am Board angekommen ist
("interacting_with_board"), verschiebt es dann sichtbar und laesst die
Persona danach eine Sekunde stehen, bevor sie den Rueckweg antritt.
applyPendingTicketMoves() in office-scene.js kapselt die dafuer noetige
Merge-Logik pur und testbar; office-render.js reicht die passenden
onArrived-Callbacks an triggerDoorVisit()/triggerPoVisit() durch.
Lange Meldungen liefen ueber den Monitorrahmen hinaus in die Szene. Jedes
Event belegt jetzt zwei Zeilen (Zeit + System, darunter eingerueckt die
Meldung), beide auf die Innenbreite gekuerzt. Die vollstaendige Meldung
zeigt ein <title>-Tooltip beim Hover ueber das Event.
Die Kuerzung selbst sitzt als truncateToWidth() in office-scene.js und ist
damit ohne DOM testbar; die Zeichenbreite ist an der breitesten der in
Frage kommenden Monospace-Schriften ausgerichtet, damit auf keinem System
etwas ueberlaeuft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Laeuft einem Agenten die Claude-Anmeldung aus, laeuft das Cron-Skript um ihn
herum unbeeindruckt weiter: es meldet "working", ruft claude auf, bekommt nichts
Brauchbares zurueck und meldet am Ende "idle". last_seen_at ist frisch, der
Agent sieht beschaeftigt aus - waehrend Lauf fuer Lauf nichts entsteht. Der
Ausfall fiel bisher erst auf, wenn jemand merkte, dass keine PRs mehr kommen.
Agenten melden den Fall jetzt ueber zwei neue state-Werte (auth_expiring,
auth_expired) am bestehenden Activity-Endpunkt. state ist serverseitig nicht
eingeschraenkt, daher ohne Migration und ohne Aenderung an der API.
Dargestellt in drei Stufen der Aufmerksamkeit:
- Schloss ueber dem Avatar (bei auth_expired pulsierend), entsaettigter Koerper,
eingefaerbter Bildschirm und Namensschild am Platz
- Header-Banner mit den betroffenen Agenten, gelb bei Vorwarnung, rot bei
Ausfall - auch aus einigen Metern Entfernung noch lesbar
- KPI-Kachel "Problem: n", die sich nur einfaerbt, wenn n > 0
Kern ist isAgentVisible(), bewusst getrennt von isAgentPresent(): ein
blockierter Agent bleibt sichtbar, obwohl er sich nicht mehr meldet, zaehlt aber
nicht als "Online" mit. Ohne das verschwaende er nach dem Praesenz-Timeout genau
dann vom Schreibtisch, wenn seine Warnung dort stehen soll.
MAX_KPI_TILES von 4 auf 5, sonst verdraengen Agenten/Online/Problem/Hooks die
gemeldeten KPIs (F7) vollstaendig.
Nebenbei: "npm test" lief seit Node 24 nicht mehr (das Verzeichnis-Argument wird
nicht mehr als Testverzeichnis aufgeloest), jetzt per Glob.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die im Issue beschriebene Event-Anzeige (neuestes Event oben, aeltere
schieben nach, Ueberschuss wird abgeschnitten) ist bereits seit Phase 4
umgesetzt (buildEventLines()/MAX_EVENT_LINES, F5) und braucht keine
Aenderung.
Neu ist die vierte, immer sichtbare KPI-Kachel ganz rechts im
KPI-Monitor: "Hooks: n" zaehlt die seit dem letzten Start des
api-Containers empfangenen Webhooks. Der Zaehler ist dateibasiert
(Metrics\HookCounter), weil der eingebaute PHP-Server jede Anfrage als
eigene Skriptausfuehrung behandelt; docker/entrypoint.sh setzt die Datei
beim Start des api-Containers (nicht des sync-Containers) zurueck. Neuer
oeffentlicher Endpunkt GET /api/v1/webhooks/stats liefert den Stand,
das Frontend haengt ihn als eigene Kachel an (buildHooksKpi()) und
reserviert ihr dafuer eine feste Kachel statt sie der MAX_KPI_TILES-
Kappung der uebrigen KPIs zu unterwerfen. Der Wert fliesst zusaetzlich
in den SSE-Fingerabdruck (ChangeFeed) ein.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die KPI-Kacheln "Agenten" (registrierte Agenten) und "Online" (davon
in den letzten 10 Minuten aktiv, siehe AgentRepository::isPresent())
wurden auf der Monitor-Wand nie angezeigt. Statt eine eigene
Meldepflicht dafuer einzufuehren, leitet buildAgentCountKpis() beide
Werte direkt aus der ohnehin geladenen Agentenliste ab und stellt sie
den ueber /api/v1/kpis gemeldeten Kennzahlen voran.
Schliesst #39
Statuswechsel von/zu "in_arbeit" (Label "wip") loest ein Agent selbst aus,
wenn er ein Ticket nimmt bzw. abgibt, und meldet die Bewegung ueber seinen
eigenen state. detectUnassignedTicketChanges() zaehlte diese Wechsel
bislang trotzdem als "niemandem zugeordnet" und liess zusaetzlich den PO
dafuer zum Board laufen.
Schliesst #32
Das Projekte-Modal am PO laesst seit #27 je Projekt eine Farbe pflegen, und
GET /api/v1/tickets liefert sie pro Ticket mit (ticket.color) - auf dem Board
kam sie aber nie an: renderBoard() bekam nur Zaehler je Spalte, jeder Zettel
war derselbe gelbe Standardzettel.
buildBoardColumnLayout() bekommt deshalb zusaetzlich die gruppierten Tickets
und liefert die Farbe je Zettel mit. Ohne Ticketliste (Demo-Modus, der nur
Zaehler kennt) bleibt alles wie bisher.
Ein Stapel steht fuer mehr Tickets als er Zettel hat und zeigt die ersten
verschiedenen Farben darin - so ist auch an "Done" (immer ein Stapel) zu
sehen, aus welchen Projekten die Tickets stammen. Reichen die Farben nicht
fuer alle drei Zettel, werden sie zyklisch wiederholt: ein ungefaerbter
Rest-Zettel saehe sonst wie ein weiteres Projekt aus, denn --color-note ist
von einem gelben Projekt kaum zu unterscheiden.
Gefaerbte Zettel bekommen ausserdem eine neutrale statt der gelben Kontur.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Codeberg-Sync liest nun Issues aus mehreren konfigurierbaren Projekten
(Config::codebergRepos(), Default: fds2610/monitor gelb, fds2610/Steuerkram
gruen, fds2610/nc-gantt blau) statt nur aus einem einzigen Repo. Damit
external_ref (Issue-Nummer) projektuebergreifend nicht kollidiert, ist es
jetzt zusammen mit dem neuen Ticket-Feld "repo" eindeutig; Migration
002_multi_repo_tickets.sql ergaenzt die Spalte und den Index. Da Migrationen
dadurch nicht mehr rein additiv sind, trackt Database::migrate() jetzt
angewandte Dateien in schema_migrations, damit ALTER TABLE nicht bei jedem
Prozessstart erneut laeuft. Das Frontend baut Codeberg-Links jetzt aus dem
repo-Feld jedes Tickets statt aus einer global fixen owner/repo-Angabe.
Schliesst #26
Der Client verglich last_seen_at bislang selbst gegen Date.now() - je nach
Client-Zeitzone/-Uhr konnte das falsche Ergebnisse liefern und liess Agenten
faelschlich als abwesend erscheinen (Issue #20, Folge von #17). Die API
liefert die Anwesenheit jetzt direkt als is_present-Feld mit, berechnet
serverseitig via gmdate()/time() (AgentRepository::isPresent()). Das Frontend
liest das Feld nur noch aus, ohne eigene Zeit-Arithmetik.
Der Product Owner ("PO") ist keine ueber die API registrierte Rolle, sondern
repraesentiert die Produktverantwortung des Systems selbst: eigener, fester
Platz ausserhalb des dynamischen 8er-Schreibtisch-Rasters, anwesend genau
dann, wenn die API erreichbar ist (statt ueber last_seen_at). Ausserdem laeuft
er zum Board, sobald sich dort ein Ticket-Status aendert, der noch keiner
anderen Rolle zugeordnet ist (z.B. Wechsel nach "bereit" durchs Label
"automate", wie es diesem Issue selbst passiert ist) - Wechsel nach
fertig/done bleiben weiterhin Sache der Rolle "user" (Tuerbesuche).
Schliesst #19
Ein registrierter Agent gilt im Bueromonitor nur noch als anwesend,
solange last_seen_at hoechstens zehn Minuten zurueckliegt (isAgentPresent,
office-scene.js). Meldet er sich laenger nicht, bleibt sein Schreibtisch
frei und er erscheint auch nicht mehr im Ueberlauf-Ruheplatz vor der Tuer,
statt weiterhin faelschlich als anwesend dargestellt zu werden.
Schliesst #17
Der fett gedruckte Titel "Buero" ueber der Visualisierung heisst jetzt
"Agent-Status", der laengere erklaerende Fliesstext darunter entfaellt.
Stattdessen zeigt der Header rechtsbuendig einen rein kosmetischen
Sekunden-Countdown, der von MONITOR_SYNC_INTERVAL herunterzaehlt und nach
Erreichen von 0 wieder von vorn beginnt (Issue #12). Der Wert wird dazu wie
MONITOR_API_BASE per config.js/envsubst ans Frontend durchgereicht.
Phase 6 (F2): detectDoorVisits() erkennt die drei Anlaesse aus den Detailantworten
(neues per Codeberg-Sync angelegtes Backlog-Ticket, Ticket erreicht "fertig", Ticket
erreicht "done") durch Diff zweier Ticket-Snapshots. office-render.js laesst dafuer
einen "user"-Besucher durch die linke Tuer hereinkommen, zum Board laufen, kurz
interagieren und wieder hinausgehen - unabhaengig vom Daten-Refresh-Takt, damit ein
Besuch auch bei einem zwischenzeitlichen Refresh sauber zu Ende animiert.
Phase 7 (F16): html/mon.html, script.js und styles.css sind entfallen ("kann
entfallen" laut Detailantworten); check_fds.sh/mail_fds.py/status.txt speisen
weiterhin unveraendert den System-Monitor. Unit-Tests fuer die neue Tuer-Logik
ergaenzt (weiterhin 100% Line-Coverage, node --test). E2E-Tests bleiben bewusst
ausserhalb dieser Phase.
Ausserdem: update.sh (holt die neueste Version vom konfigurierten Git-Remote und
faehrt die Docker-Compose-Entwicklungsumgebung hoch) und register-agent.sh
(Hilfsskript zur Agenten-Registrierung per API) ergaenzt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Setzt Visualization.md Abschnitt 9, Phasen 3-5 vollstaendig um:
Phase 3 (Kanban-Board live): Board zeigt echte Ticket-Daten aus GET /api/v1/tickets
(office-api.js), Klick auf eine Spalte oeffnet ein Modal mit Titel/Beschreibung/Typ und
einem Link auf die Codeberg-Quelle bei per Sync angelegten Tickets (F4).
Phase 4 (Monitor-Wand live): Event-, System- und KPI-Monitor zeigen echte Daten,
Klick-Modals fuer alle drei. Neuer SSE-Endpoint GET /api/v1/stream (F13) meldet per
ChangeFeed-Fingerabdruck, welche Ressourcen sich geaendert haben; office-realtime.js nutzt
EventSource mit Polling-Fallback. KPI-Monitor zeichnet eine eigene SVG-Sparkline (F10, kein
Chart-Lib) sobald KPIs gemeldet wurden, sonst weiterhin der Phase-2-Platzhalter (F7 bleibt
inhaltlich offen). API-Antworten tragen jetzt CORS-Header, da Frontend (:8090) und API
(:8091) im Docker-Compose-Setup unterschiedliche Origins sind.
Phase 5 (Agenten & Animation): resolveAgentVisualState bildet gemeldete Agenten-Zustaende
auf Ort/Pose ab; Agenten-Avatare sind eine per CSS transition animierte, von Board/
Schreibtisch-Moebeln entkoppelte Schicht, die zwischen Schreibtisch, Board, Monitor-Wand und
einer neuen Kaffee-Ecke laufen. Idle-Varianten (Zeitung/Kaffee/Schwaetzchen) werden rein
kosmetisch client-seitig zufaellig ausgeloest (F8), eine AnimationQueue serialisiert
Update-Animationen bei vielen gleichzeitigen Ereignissen (F9).
29 Node-Tests (100% Line-Coverage office-scene.js) und neue PHPUnit-Tests fuer
Response::stream(), ChangeFeed, StreamController und die neuen Repository::fingerprint()-
Methoden. PHP/Docker-Ausfuehrung konnte in dieser Umgebung nicht verifiziert werden (kein
PHP verfuegbar) - vor dem Merge bitte `docker compose run --rm api composer test` pruefen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Setzt Phase 2 aus Visualization.md um: Vanilla-SVG-Buero-Szene (Waende, 2 Tueren,
8 Schreibtische, Kanban-Board-Rahmen mit 7 Spalten, Monitor-Wand mit Event-/System-/
KPI-Monitor) ohne Animation, gespeist mit statischen Demo-Daten im Format der
Phase-1-API-Responses. Board-Stapel-Logik (>5 Tickets, Done-Spalte als Dauerstapel)
folgt Detailantworten.md F2/F3.
Reine Layout-Logik (html/js/office-scene.js) ist ausgelagert und mit dem Node-
Testrunner abgedeckt (100% Zeilenabdeckung, tests/frontend/), das DOM-Rendering
(office-render.js) bleibt bewusst duenne Glue-Logik. Docker-Compose um web- (nginx,
serviert html/) und frontend-Service (node, "npm test") erweitert, analog zum
bestehenden api-Service und zum NC-Gantt-Vorbild: kein PHP/Node auf dem Host noetig.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>