Pinky Z: SSE consumer — push-driven dashboard over the events bridge (v1.30.0) #56

Merged
ClaudiuSchuster merged 1 commit from oss-oo/pinky-z-sse into main 2026-10-01 15:30:15 +00:00
Owner

Migrates the dashboard from HTTP polling to EventSource consumption of the events bridge (zcode-dispatch v1.0.8, docs/EVENTS.md contract) with honest degradation to the existing polling machinery.

  • D1: ZDO_EVENTS_URL knob (default http://127.0.0.1:8788/events; empty/off = pure v1.29 polling world), served once via GET /api/config — static page, SSE armed only on non-null URL.
  • D2: typed event→UI mapping (turns → refresh + open-panel reload, notification-delivered → dock/unread, lifecycle/contract → refresh, ping/mqtt → liveness), ~200 ms trailing-edge coalescing, envelope digest trusted (never recomputed in JS).
  • D3: single-owner syncPollTimers materializes every timer from intent; healthy push idles the main cycle + dock poll (drawer/modal keep 5 s streaming semantics — mid-turn parts carry no MQTT event); degradation shows the compact ⚠ push offline — polling chip and re-arms exactly the v1.27 governor behavior; bridge.hello always resyncs from state; bounded revival (15 s watchdog + /healthz probe).
  • Documented deviations (both with empirical probes): bridge.dropped KEEPS the connection (close() provably never auto-reconnects in Chrome — the written recipe would freeze the feed; the gap closes via one immediate full refresh, native Last-Event-ID replay stays available); a one-shot 45 s post-revival fresh-guard heals the restarted-bridge skip window (stale high Last-Event-ID silences the new process’s live seqs — bridge-side edge reported for Brain-A’s lane).
  • Safety resync once per quiet minute bounds unmapped-signal staleness (desktop sessions) without adding requests while events flow.

Validation: suite 110 green (100 prior + 9 config-endpoint + node-harness module tests); Super-Linter station recipe all lanes green (pylint 10.00/10). Fixture rig (mini MQTT broker + the real bridge from zcode-dispatch main, loopback free ports): turn-completed reflection 0.26 s with zero /api/sessions|usage polls across a 40 s quiet window (pings flowing, timer handles null); bridge kill → chip in 0.0 s, polls at cadence, mutation via poll 2.1 s, revival 2.8 s; off-world zero SSE attempts byte-for-byte; dropped burst (328 events) resync + continued live delivery; organic reconnect replayed the full 8-event ring via truncated hello in 3.0 s; restart deaf-window healed in 52 s; CPU A/B degraded vs off 0.97×/0.84×.

Migrates the dashboard from HTTP polling to EventSource consumption of the events bridge (zcode-dispatch v1.0.8, docs/EVENTS.md contract) with honest degradation to the existing polling machinery. - **D1**: `ZDO_EVENTS_URL` knob (default `http://127.0.0.1:8788/events`; empty/`off` = pure v1.29 polling world), served once via `GET /api/config` — static page, SSE armed only on non-null URL. - **D2**: typed event→UI mapping (turns → refresh + open-panel reload, notification-delivered → dock/unread, lifecycle/contract → refresh, ping/mqtt → liveness), ~200 ms trailing-edge coalescing, envelope digest trusted (never recomputed in JS). - **D3**: single-owner `syncPollTimers` materializes every timer from intent; healthy push idles the main cycle + dock poll (drawer/modal keep 5 s streaming semantics — mid-turn parts carry no MQTT event); degradation shows the compact `⚠ push offline — polling` chip and re-arms exactly the v1.27 governor behavior; `bridge.hello` always resyncs from state; bounded revival (15 s watchdog + /healthz probe). - **Documented deviations** (both with empirical probes): `bridge.dropped` KEEPS the connection (close() provably never auto-reconnects in Chrome — the written recipe would freeze the feed; the gap closes via one immediate full refresh, native Last-Event-ID replay stays available); a one-shot 45 s post-revival fresh-guard heals the restarted-bridge skip window (stale high Last-Event-ID silences the new process’s live seqs — bridge-side edge reported for Brain-A’s lane). - Safety resync once per quiet minute bounds unmapped-signal staleness (desktop sessions) without adding requests while events flow. **Validation**: suite 110 green (100 prior + 9 config-endpoint + node-harness module tests); Super-Linter station recipe all lanes green (pylint 10.00/10). Fixture rig (mini MQTT broker + the real bridge from zcode-dispatch main, loopback free ports): turn-completed reflection **0.26 s** with **zero** /api/sessions|usage polls across a 40 s quiet window (pings flowing, timer handles null); bridge kill → chip in 0.0 s, polls at cadence, mutation via poll 2.1 s, revival 2.8 s; off-world zero SSE attempts byte-for-byte; dropped burst (328 events) resync + continued live delivery; organic reconnect replayed the full 8-event ring via truncated hello in 3.0 s; restart deaf-window healed in 52 s; CPU A/B degraded vs off 0.97×/0.84×.
Pinky Z: SSE consumer — push-driven dashboard over the events bridge (v1.30.0)
All checks were successful
Checks / Functional checks (pull_request) Successful in 19s
e7a637c578
The dashboard consumes Brain-A's events bridge (zcode-dispatch v1.0.8
`stream.py events`, the zcode/events/v1 envelope) as an EventSource:
event-driven refreshes with the HTTP poll cycle provably idle while the
feed is healthy, honest degradation to polling the moment it is not.

- D1: ZDO_EVENTS_URL knob (default http://127.0.0.1:8788/events; empty
  or "off" = pure v1.29 polling world) served once via GET /api/config
  — the page stays a static file, arms SSE only on a non-null URL.
- D2: typed event->UI mapping per docs/EVENTS.md (turns refresh + open
  panel reload, notification-delivered drives dock/unread, lifecycle +
  contract events refresh, ping/mqtt liveness only), trailing-edge ~200 ms
  coalescing, digest trusted from the envelope (never recomputed in JS).
- D3: one poll-governance materializer (syncPollTimers) owns every timer
  variable — hidden tab pauses all, healthy push idles the main cycle +
  dock poll (drawer/modal keep their 5 s streaming semantics: mid-turn
  parts carry no MQTT event), degradation re-arms exactly the v1.27
  governor behavior with a compact "⚠ push offline — polling" chip and
  bounded revival (15 s watchdog with /healthz probe + browser-retry
  replacement), bridge.hello always resyncs from state (ids reset per
  bridge process; replayTruncated forces one full refresh).
- bridge.dropped: documented deviation — the contract's close() recipe
  provably freezes the feed (Chrome never reconnects a closed
  EventSource; probed 2026-10-01), so the connection is KEPT (native
  Last-Event-ID replay stays available) and the gap closes via one
  immediate full refresh. A post-revival fresh-guard (45 s, one-shot,
  cancelled by any delivered event) heals the restarted-bridge skip
  window observed empirically (stale high Last-Event-ID silences the
  new process's live seqs).
- Safety resync once per quiet minute bounds unmapped-signal staleness
  (desktop sessions write the DB with no bus event) without adding a
  single request while events flow.

Tests: events_url/config endpoint (9), node-harness module tests for
mapping/coalescing/watchdog/hello/dropped/chip/off-world/fresh-guard
(16 groups) — suite 110 green (was 100). Super-Linter station recipe:
all lanes green, pylint 10.00/10.

Fixture-rig validation (mini MQTT broker + the real bridge, pulled from
zcode-dispatch main, loopback free ports): G1 reflection 0.26 s with
zero /api/sessions|usage polls across a 40 s quiet window (pings
flowing, timer handles null); G2 chip in 0.0 s on bridge kill, polls at
cadence, mutation via poll in 2.1 s, revival in 2.8 s; off-world zero
SSE attempts; G3 dropped burst (328 events) resync + live delivery,
organic reconnect replayed the full 8-event ring via truncated hello in
3.0 s, restart deaf-window healed by the fresh guard in 52 s; CPU A/B
degraded vs off: 0.97x observatory, 0.84x chrome — the SSE client is
~free.
ClaudiuSchuster deleted branch oss-oo/pinky-z-sse 2026-10-01 15:30:15 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
OSS-Singularity/zcode-dispatch-observatory!56
No description provided.