fix(dashboard): topology reflects connection health + clears finished requests - #7672
diegosouzapw merged 2 commits into
Conversation
… requests The provider topology only lit nodes from live/recent traffic, so between requests (and right after a restart) it went blank even though 50+ connections were healthy — which reads as "lost providers". Two root causes: 1. Stuck-green latch: request.completed/request.failed are declared in the dashboard event map and consumed by useLiveRequests to drain the active-request set, but they were never emitted (only request.started was). A node's green "active" pulse therefore only cleared on a page reload, and accumulated over a session. Emit the terminal event from persistAttemptLogs — keyed by the same traceId as request.started — through a pure resolveRequestLifecycleEvent() helper (2xx/3xx + no error => completed, else failed). 2. No at-rest state: the map had nothing to show when idle. Colour each node by connection health (green connected / red error / grey idle) as a base layer, with live/recent traffic still taking precedence and pulsing brighter on top. edgeStyle() gains an optional trailing `healthy` param (static dim green) and StatusDot a `pulse` prop (static dot for connected-at-rest); both backward compatible. Legend "Active" -> "Connected". Tests: resolveRequestLifecycleEvent success/failure/token-alias units, edgeStyle healthy variant + precedence, and source guards for the emit wiring (traceId threaded into persistAttemptLogs) and the health-colour wiring.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
Resolve conflicts in HomeProviderTopologySection.tsx (keep i18n-compliant
tCommon("active") label, add PR's status field) and edgeStyles.ts (keep
PR's healthy-state branch stacked on release's idle color/opacity update);
repair a stale duplicate assertion in edgeStyles.test.ts left by the
automerge (var(--color-border)/0.2 -> var(--color-text-muted)/0.3).
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
|
Thanks for tracking down both root causes — the "stuck green" latch is confirmed real (grepped the release branch: request.completed/request.failed are declared in types.ts but were never emitted anywhere before this PR). resolveRequestLifecycleEvent and the edgeStyle/StatusDot unit tests all pass for me locally (17/17 across the three files). Two things to fix before merge:
Note: the pure logic (resolveRequestLifecycleEvent, edgeStyle precedence, per-provider health derivation) is unit-tested and I ran it green — nice work there. The on-screen coloring/pulsing itself is UI-only and I haven't visually verified it on a running instance; a screenshot or two (light+dark) alongside your existing claim would help reviewers confirm. |
|
Good news — the two conflicts from last review are resolved now. CI is currently red, but that's a shared base/infra issue hitting the whole PR queue right now (confirmed identical failure signature on an unrelated PR), not something in your diff. We still owe you a check on the i18n label item flagged earlier; will confirm once the base-red is cleared and CI re-runs green. |
… (owner-approved) The /fix-prs validation-train sweep surfaced a cluster of otherwise-clean contributor feature PRs (#6973/#7683/#7662/#7672/#7633/#7767) whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit complexity slack (2056 vs 2059). This was the 4th such block of the day (#7695/#7747/#7768 each needed helper extraction earlier). Owner approved raising both ceilings to give new-feature PRs breathing room: complexity to 2072 (combined-cluster 2068 + 4 headroom), cognitive to 900 (combined 896 + 4). Structural shrink stays debt (#3501); tighten via --update next cycle.
|
Validated in local merge-train runs 4+5 on 192.168.0.113 @ a00def8f1/477d9f4d3 (11-PR batch: static gates green ×2; test:unit union green — 24512/24529 + 24504/24521, residual fails proven environmental (/tmp stale) + timing-flake (6/6 isolated); vitest 260/260 on the equivalent local tree). Suite logs: /srv/omniroute-train/.claude/worktrees/merge-train-20260719-{231?,233341}-suite.log + /tmp/mt-full.log |
18a8da6
into
diegosouzapw:release/v3.8.49
…t contract The Recent Requests panel added five `home` keys to en.json but only vi.json was translated, so the en↔locale key-parity guard (diegosouzapw#6695) failed. Run the sanctioned `i18n:sync-ui` to mirror them into the remaining 41 locales; untranslated entries carry the standard `__MISSING__:<en>` marker, which `deepMergeFallback` renders as the clean English value until a translation pass lands. vi.json keeps its real translations. Also rewrite tests/unit/topology-connection-health.test.ts. It guarded diegosouzapw#7672's connection-health base layer (healthy-but-idle drawn green), which this branch deliberately replaces with a calm-at-rest map: only live traffic or a real error lights a node. The test now pins the current contract instead — enabled-connection gating, no ghost nodes from all-time call_logs, neutral border at rest, dots only for traffic/errors, and stable alphabetical ring slots so layout never depends on activity. Legibility is preserved structurally (presence + stable position) rather than by a rest colour.
The topology rework replaces the connection-health rest layer from diegosouzapw#7672 with a calm-at-rest map (only live traffic or a real error lights a node/edge), but three existing guards still asserted the previous behaviour: - ui/edgeStyles: pinned the pre-retune rest opacities (last 0.6 / idle 0.3 and a healthy 0.4 green base). Retuned to the shipped values and extended with a relationship invariant so any future retune must keep every resting state well below live traffic in both opacity and stroke width. - ui/home-provider-topology-section-4606: looked for a Card wrapper. The section's frame is now a bordered but transparent div (an opaque surface hid the page's graph-paper wallpaper behind the graph), so the framing contract is asserted directly, and the Recent Requests child is covered including its gate flag. - call-logs-exclude-tests-allowlist: dropped an explicit `any` on the row mapper; getCallLogs already returns a typed row, so the annotation was unnecessary. The coverage is kept as real regression guards for the new design rather than deleted, and each file documents what changed and why.
… (owner-approved) The /fix-prs validation-train sweep surfaced a cluster of otherwise-clean contributor feature PRs (diegosouzapw#6973/diegosouzapw#7683/diegosouzapw#7662/diegosouzapw#7672/diegosouzapw#7633/diegosouzapw#7767) whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit complexity slack (2056 vs 2059). This was the 4th such block of the day (diegosouzapw#7695/diegosouzapw#7747/diegosouzapw#7768 each needed helper extraction earlier). Owner approved raising both ceilings to give new-feature PRs breathing room: complexity to 2072 (combined-cluster 2068 + 4 headroom), cognitive to 900 (combined 896 + 4). Structural shrink stays debt (diegosouzapw#3501); tighten via --update next cycle.
… requests (diegosouzapw#7672) The provider topology only lit nodes from live/recent traffic, so between requests (and right after a restart) it went blank even though 50+ connections were healthy — which reads as "lost providers". Two root causes: 1. Stuck-green latch: request.completed/request.failed are declared in the dashboard event map and consumed by useLiveRequests to drain the active-request set, but they were never emitted (only request.started was). A node's green "active" pulse therefore only cleared on a page reload, and accumulated over a session. Emit the terminal event from persistAttemptLogs — keyed by the same traceId as request.started — through a pure resolveRequestLifecycleEvent() helper (2xx/3xx + no error => completed, else failed). 2. No at-rest state: the map had nothing to show when idle. Colour each node by connection health (green connected / red error / grey idle) as a base layer, with live/recent traffic still taking precedence and pulsing brighter on top. edgeStyle() gains an optional trailing `healthy` param (static dim green) and StatusDot a `pulse` prop (static dot for connected-at-rest); both backward compatible. Legend "Active" -> "Connected". Tests: resolveRequestLifecycleEvent success/failure/token-alias units, edgeStyle healthy variant + precedence, and source guards for the emit wiring (traceId threaded into persistAttemptLogs) and the health-colour wiring. Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
… (owner-approved) The /fix-prs validation-train sweep surfaced a cluster of otherwise-clean contributor feature PRs (diegosouzapw#6973/diegosouzapw#7683/diegosouzapw#7662/diegosouzapw#7672/diegosouzapw#7633/diegosouzapw#7767) whose per-PR +1/+2 own-growth collectively exceeded the tip's 3-unit complexity slack (2056 vs 2059). This was the 4th such block of the day (diegosouzapw#7695/diegosouzapw#7747/diegosouzapw#7768 each needed helper extraction earlier). Owner approved raising both ceilings to give new-feature PRs breathing room: complexity to 2072 (combined-cluster 2068 + 4 headroom), cognitive to 900 (combined 896 + 4). Structural shrink stays debt (diegosouzapw#3501); tighten via --update next cycle.
… requests (diegosouzapw#7672) The provider topology only lit nodes from live/recent traffic, so between requests (and right after a restart) it went blank even though 50+ connections were healthy — which reads as "lost providers". Two root causes: 1. Stuck-green latch: request.completed/request.failed are declared in the dashboard event map and consumed by useLiveRequests to drain the active-request set, but they were never emitted (only request.started was). A node's green "active" pulse therefore only cleared on a page reload, and accumulated over a session. Emit the terminal event from persistAttemptLogs — keyed by the same traceId as request.started — through a pure resolveRequestLifecycleEvent() helper (2xx/3xx + no error => completed, else failed). 2. No at-rest state: the map had nothing to show when idle. Colour each node by connection health (green connected / red error / grey idle) as a base layer, with live/recent traffic still taking precedence and pulsing brighter on top. edgeStyle() gains an optional trailing `healthy` param (static dim green) and StatusDot a `pulse` prop (static dot for connected-at-rest); both backward compatible. Legend "Active" -> "Connected". Tests: resolveRequestLifecycleEvent success/failure/token-alias units, edgeStyle healthy variant + precedence, and source guards for the emit wiring (traceId threaded into persistAttemptLogs) and the health-colour wiring. Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com> Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
What
The home-dashboard provider topology only coloured nodes from live/recent traffic.
Between requests — and right after a restart — the map went blank even though 50+
connections were healthy, which reads as "I lost all my providers". Two independent
root causes, fixed together.
1. Stuck-green latch (live pipeline)
request.completed/request.failedare declared in the dashboard event map andconsumed by
useLiveRequeststo drain the active-request set, but they were neveremitted — only
request.startedwas (chatCore.ts:410). So a node's green "active"pulse was a one-way latch: it lit on request start and only cleared on a page reload,
accumulating over a session and disappearing on restart.
Fix: emit the terminal event from
persistAttemptLogs(the per-attempt completionpoint, correct for both streaming and non-streaming), keyed by the same
traceIdasrequest.started, via a pureresolveRequestLifecycleEvent()helper (2xx/3xx and noerror ⇒
request.completed, elserequest.failed). Deferred withsetImmediateoffthe response hot path, mirroring
request.started.2. No at-rest state (visualisation)
The map had nothing to show when idle. Each node is now coloured by connection
health (green connected / red error / grey idle) as a base layer; live and recent
traffic still take precedence and pulse brighter on top.
edgeStyle()gains anoptional trailing
healthyparam (static dim green) andStatusDotapulseprop(static dot for connected-at-rest) — both backward compatible, so the Combo/Compression
studios that share the flow palette are unaffected. Legend "Active" → "Connected".
Validation (Hard Rule #18)
tests/unit/topology-request-lifecycle-emit.test.ts—resolveRequestLifecycleEventsuccess / failure / token-alias units + guards that the emit exists and that
traceIdis threaded intopersistAttemptLogs(pairs withrequest.started).tests/unit/topology-connection-health.test.ts— health derivation + node/edge wiring.tests/unit/ui/edgeStyles.test.ts— newhealthyedge variant +error > active > last > healthyprecedence.npm run typecheck:coreclean;npm run lintclean; existing topology/edge suites green (Node + Vitest).request.startedon the dashboard WS, confirming the in-process eventBus → embeddedWS-server path works. The new terminal emit rides the exact same path and is unit-tested.
Scope
No API or DB-schema changes. Security- and PII-sensitive paths untouched. Helper
signature additions are backward compatible.