Buero-Visualisierung: PO-Agent unabhaengig von API-Erreichbarkeit immer anzeigen

Der PO laeuft auf dem Monitoring-Server selbst und repraesentiert dessen
interne Prozesse. Bisher wurde er als "abwesend" gezeichnet, sobald der
Browser die API kurzzeitig nicht erreichen konnte (isLive=false) - obwohl
der Server und seine Prozesse in diesem Fall weiterliefen. Der feste
PO-Platz zeigt den PO jetzt unabhaengig von isLive.

Schliesst #97

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
fds2610-bot 2026-09-23 09:00:28 +02:00
parent 6a35712d66
commit a7eb91ac40
2 changed files with 17 additions and 18 deletions

View file

@ -776,8 +776,8 @@ function renderDesk({ deskIndex, agent }) {
/**
* @param {Array<object>} desks - reguläre 8er-Raster-Plaetze (echte Agenten, F1).
* @param {object|null} poAgent - {name: "PO", role: "product_owner", pose} bei erreichbarer
* API, sonst null (dann zeigt der feste PO-Platz "frei", Issue #19).
* @param {object|null} poAgent - {name: "PO", role: "product_owner", pose}, immer gesetzt (der
* PO gilt unabhaengig von der API-Erreichbarkeit als anwesend, Issue #19/#97).
* @param {() => void} onPoClick - oeffnet das Projekte-Modal (Issue #27).
*/
function renderDesks(desks, poAgent, onPoClick) {
@ -1241,17 +1241,15 @@ function repaintAgentsLayer() {
// es nur einen PO - poState ist daher ein einzelner Zustand statt einer Map.
// ---------------------------------------------------------------------------------------
let poIsLive = false;
let poState = "idle";
let poVisitTimeoutId = null;
// Issue #55: wird aufgerufen, sobald der laufende Besuch das Board erreicht - das ist der
// richtige Zeitpunkt, um die bis dahin zurueckgehaltenen Ticket-Aenderungen sichtbar zu machen.
let poOnArrived = null;
// Der PO gilt immer als anwesend (Issue #97, siehe Kommentar bei poDeskAgent in
// renderOfficeScene()), poPlacement() liefert daher ohne eigene Bedingung eine Platzierung.
function poPlacement() {
if (!poIsLive) {
return [];
}
const visual = resolveAgentVisualState(poState);
return [
{
@ -1295,7 +1293,7 @@ function advancePoVisit() {
// Laeuft bereits ein Besuch, gibt es dafuer keine eigene Animation mehr - onArrived wird dann
// sofort aufgerufen, damit die zurueckgehaltene Aenderung nicht dauerhaft verborgen bleibt.
function triggerPoVisit(onArrived) {
if (!poIsLive || poState !== "idle") {
if (poState !== "idle") {
onArrived?.();
return;
}
@ -1315,7 +1313,7 @@ function triggerPoVisit(onArrived) {
// Ist der PO gerade anderweitig unterwegs (poState !== "idle"), wird kein zweiter Besuch
// angestossen - die Aktion laeuft trotzdem, nur ohne eigene Animation.
function triggerPoReloadVisit(action) {
if (!poIsLive || poState !== "idle") {
if (poState !== "idle") {
action();
return;
}
@ -2355,10 +2353,6 @@ export function renderOfficeScene(container, data = {}) {
poState = "idle";
}
// Der PO gilt als anwesend, sobald die API erreichbar ist (isLive) - nicht ueber das
// is_present-Feld wie registrierte Agenten (Issue #19).
poIsLive = isLive;
// "Agenten"/"Online" (Issue #39) stehen vor den gemeldeten KPIs (F7), damit sie auf der
// Wandkachel (MAX_KPI_TILES) immer sichtbar sind, statt von gemeldeten Kennzahlen verdraengt
// zu werden. "Hooks" (Issue #38) reserviert sich zusaetzlich die letzte (rechte) Kachel -
@ -2420,10 +2414,13 @@ export function renderOfficeScene(container, data = {}) {
agent && agent.role === "voice" ? { ...agent, pending_recordings: pendingRecordings } : agent
);
const deskLayout = buildDeskLayout(deskAgents);
const poDeskAgent = isLive ? { name: PO_DISPLAY_NAME, role: "product_owner", pose: "idle" } : null;
// Auch ohne erreichbare API klickbar: das Modal sagt dann selbst, dass es die Projekte
// nicht laden konnte. Ein toter PO waere in genau der Lage, in der man nachsehen will,
// die schlechtere Antwort (Fehlerbericht zu Issue #27).
// Der PO laeuft auf dem Monitoring-Server selbst und repraesentiert dessen interne Prozesse
// (Sync/API) - er gilt deshalb immer als anwesend, unabhaengig davon, ob der Browser die API
// gerade erreichen kann (isLive). Vor Issue #97 verschwand der PO faelschlich mitsamt der
// Live-Szene, sobald ausgerechnet der eigene Client offline war, obwohl der Server selbst
// weiterlief. Auch ohne erreichbare API bleibt der Platz zudem klickbar: das Modal sagt dann
// selbst, dass es die Projekte nicht laden konnte (Fehlerbericht zu Issue #27).
const poDeskAgent = { name: PO_DISPLAY_NAME, role: "product_owner", pose: "idle" };
const desksGroup = renderDesks(deskLayout, poDeskAgent, openRepoConfigModal);
const existingDesks = svg.querySelector(".desks");
if (existingDesks) {

View file

@ -859,8 +859,10 @@ export function advanceDoorVisitStage(stage) {
// Der PO ist keine echte Registrierung ueber POST /api/v1/agents, sondern repraesentiert die
// Produktverantwortung des Systems selbst - er bekommt daher keinen dynamisch zugewiesenen
// Schreibtisch aus dem 8er-Raster, sondern einen eigenen, festen Platz (siehe office-render.js,
// PO_DESK), und gilt als anwesend, sobald die API erreichbar ist (nicht ueber das
// is_present-Feld wie registrierte Agenten, siehe isAgentPresent()).
// PO_DESK), und gilt immer als anwesend (nicht ueber das is_present-Feld wie registrierte
// Agenten, siehe isAgentPresent()). Er laeuft auf dem Monitoring-Server selbst und
// repraesentiert dessen interne Prozesse - ob der Browser die API gerade erreichen kann, aendert
// daran nichts (Issue #97; bis dahin verschwand der PO faelschlich mit, sobald isLive false war).
export const PO_AGENT_ID = "po";
export const PO_DISPLAY_NAME = "PO";