homelab-codex-ws/docs/sessions/2026-05-27.md
Oskar Kapala 603e10a364 docs: session summary 2026-05-27 + update observer/control-plane/chelsty docs
docs/sessions/2026-05-27.md (new):
- Full session record: problems found, all commits shipped, end state
- Written in Polish per operator preference for session notes
- Known limitations: SLZB-06U offline, ezsp→ember migration pending

docs/observer-runtime.md:
- Document per-node checkpoint format (replaces old global checkpoint)
- Add service_healthy / service_recovered resolution behavior
- Document ghost key pruning (_prune_stale_world patterns)
- Add event type reference table (negative vs positive)

docs/vps-control-plane.md:
- Add container names and network_mode: host detail
- Document monitor:false, NODE_ALIAS_MAP, auto-cancel behavior
- Add piha agent-system materializer integration note
- Rewrite recovery section with actionable bootstrap-flood diagnosis
- Add action state machine (pending→approved→running→completed/cancelled)

docs/chelsty-runtime.md:
- Add chelsty-infra/chelsty-ha node table
- Document docker-compose v1 constraint (always use docker-compose, not docker compose)
- Add mosquitto network_mode:host + z2m extra_hosts:host-gateway explanation
- Add z2m config writable requirement (EROFS failure mode documented)
- Add chelsty-ha monitor:false rationale
- Add minimal configuration.yaml template for z2m

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 16:18:31 +02:00

6.6 KiB

SESSION: Stabilizacja systemu wieloagentowego homelabu

DATE: 2026-05-27
RESULT: System NOMINAL (97/97 services, 0 errors)


PROBLEMS FOUND

  • stability-agent nie generował akcji naprawczych — tylko redeploy, brak container_restart
  • mosquitto na chelsty-infra padł i nikt go nie restartował (restart policy był no)
  • zigbee2mqtt nigdy nie był wdrożony na chelsty-infra
  • node-agent był pustym szkieletem — nie emitował service_healthy, więc services.json zawsze był pusty
  • ghost services: node-agent używał c.name (może zwrócić <12hex>_real-name) zamiast etykiety com.docker.compose.service
  • materializer na piha czytał ze swojego lokalnego Redis zamiast z control-plane API — Redis zawierał 80 przestarzałych wpisów z ghost kluczami; "Copy for AI" zwracał stare dane
  • observer używał jednego globalnego checkpointu zamiast per-node — cicho pomijał katalogi z eventami sortujące się przed aktualnym checkpointem
  • supervisor nie cancelował resolved actions — pending queue rósł bez końca
  • service_healthy event nie zamykał aktywnych incydentów
  • NODE_ALIAS_MAP nie był skonfigurowany — mismatch nazw nodów między eventem a topology
  • chelsty-ha błędnie w scope monitoringu — nie ma na nim node-agenta

FIXES SHIPPED (commits in master)

7277bdc Fix Copy for AI: materializer fetches from control-plane API instead of Redis
b40b832 Fix ghost service keys from hash-prefixed Docker container names
28e9534 observer: service_healthy resolves active incidents
46ae92b supervisor: also cancel pending actions for services removed from desired state
410bfe7 zigbee2mqtt: config goes in data dir (writable), not separate ro mount
b3912fe zigbee2mqtt: use extra_hosts host-gateway instead of network_mode: host
61e07f4 zigbee2mqtt override: clear ports list for docker-compose v1 host network compat
51002d4 Fix pending actions: node_exporter, zigbee2mqtt, chelsty-ha monitoring
fb7828b supervisor: auto-cancel pending actions when drift is resolved
2f19657 fix(node-agent): unique event IDs per service to prevent same-second overwrites
267742c vps/node-agent: add network_mode: host for control-plane health probe
4e8968f Fix service health tracking: emit service_healthy, control-plane endpoint, checkpoint migration
f4a8db9 fix(observer): per-node-directory checkpoints replace single global checkpoint
a5a3e22 fix(node-agent): skip SSH config file in rsync to avoid UID ownership errors
2349de5 fix(node-agent): correct VPS_EVENTS_HOST to actual VPS Tailscale IP
65bac4e fix(node-agent): mount host SSH key into container for event shipping
96bf326 fix(observer+operator-ui): fix stale world state, dict→list API, event time filter
ae33cce feat(node-agent): add runtime overrides for piha, solaria, chelsty-infra
c5c080b feat(vps): add node-agent runtime override with NODE_NAME=vps
01b7758 feat(node-agent): implement health monitor and safe cleanup policy

Szczegóły kluczowych napraw

fix(observer): per-node checkpoints
Jeden globalny checkpoint last_processed_file cicho pomijał katalogi eventów sortujące się alfabetycznie przed ostatnim przetworzonym węzłem (np. piha/ < vps/). Zastąpiony słownikiem {"node_checkpoints": {"piha": "...", "vps": "..."}} per-node.

fix(observer): ghost key pruning
_prune_stale_world() teraz usuwa wpisy z services.json których klucz serwisu pasuje do wzorca <12hexchars>_<name> — artefakty z Docker internal state tracking.

fix(node-agent): canonical container name
check_containers() teraz używa com.docker.compose.service label jako nazwy kanonicznej. Fallback: strip hash prefix z c.name. Kontenery w stanie created są pomijane (Docker stale-state artifacts).

fix(node-agent): service_healthy emission
Node-agent teraz emituje service_healthy dla każdego uruchomionego zarządzanego kontenera co cykl. Bez tego services.json był zawsze pusty — supervisor generował flood "missing service" redeployów.

fix(supervisor): auto-cancel resolved actions
_cancel_resolved_pending_actions() przenosi pending akcje do cancelled/ gdy:

  • serwis stał się healthy (drift_resolved_auto)
  • serwis został usunięty z desired state (service_removed_from_desired_state)

fix(supervisor): monitor:false
Pole monitor: false w services.yaml wyklucza serwis z generowania akcji supervisora. Używane dla homeassistant na chelsty-ha (brak node-agenta).

fix(agent-system/materializer): control-plane API as source
Materializer na piha teraz fetchuje dane z VPS control-plane API (CONTROL_PLANE_URL=http://100.95.58.48:18180) zamiast z lokalnego Redis. Redis zawierał 80 przestarzałych wpisów. Redis path zachowany jako fallback.

fix(chelsty-infra/zigbee2mqtt): mosquitto networking
Mosquitto działa z network_mode: host — kontenery bridge nie mogą go dosięgnąć przez localhost. Rozwiązanie: extra_hosts: - "mosquitto:host-gateway" w override z2m. Nie używamy network_mode: host dla z2m bo koliduje z ports: w docker-compose v1 (1.29.2 na chelsty-infra).

fix(chelsty-infra/zigbee2mqtt): writable config
z2m migruje i nadpisuje configuration.yaml przy starcie. Config musi być w katalogu z danymi: /opt/homelab/data/zigbee2mqtt/data/configuration.yaml (read-write mount), nie w osobnym :ro wolumenie.


STAN KOŃCOWY

Node Status Serwisy
vps online control-plane (4), node-agent, node_exporter, stability-agent
piha online agent-system (4), node-agent, stability-agent, monitoring stack
solaria online node-agent, stability-agent, AI workloads
chelsty-infra online mosquitto, zigbee2mqtt (z2m łączy się gdy SLZB-06U wróci online), node-agent, stability-agent
chelsty-ha homeassistant (monitor:false — brak node-agenta, HA monitorowane pośrednio przez MQTT)

Action queue: 0 pending, 0 approved, 0 running
Incidents: 0 active
Ghost service keys: 0


ZNANE OGRANICZENIA / TODO

  • SLZB-06U (Zigbee coordinator) offline — 192.168.1.105:6638 EHOSTUNREACH z chelsty-infra. Prawdopodobnie problem sprzętowy/sieciowy po stronie 192.168.1.0/24. z2m startuje i serwuje stronę błędu na :8080 — połączy się automatycznie gdy coordinator wróci.
  • ezsp adapter w konfiguracji z2m jest deprecated — zalecana migracja do ember. Nie wymaga nowej konfiguracji, tylko zmiana pola adapter: ember w configuration.yaml.
  • chelsty-ha nie ma node-agenta. Dodać gdy będzie dostępna maszyna lub manual bootstrap.
  • Redis na piha nadal zawiera stare klucze homelab:nodes:*, homelab:incidents:* etc. — nie są już używane przez materializer w trybie API, można wyczyścić.