fix(monitoring): report a standalone Apollo as streaming when it actually is - #50
Merged
Merged
Conversation
…ally is Addresses #23, and found a live bug on the way. ## The signal was wrong HostApolloInfo.Streaming came from Apollo's serverinfo alone: state not ending in FREE, or currentgame != 0. Those describe a launched APPLICATION, not a client session. Someone streaming the plain desktop -- which is what a console Apollo is usually for -- leaves currentgame at 0 and state at SUNSHINE_SERVER_FREE for the entire session. Measured 2026-09-11: the standalone Apollo encoding steadily at ~15.8% for 26 minutes, with an encoder created in its log and never torn down, still answered state = SUNSHINE_SERVER_FREE, currentgame = 0. So /api/host showed the dashboard "not streaming" for the whole time the host WAS streaming. Streaming is now per-process GPU video encode OR the serverinfo signal, read through the same WMI GPU engine counters GpuMonitor already uses, filtered to the Apollo PID and the videoencode engine. Per process, never the GPU total -- RustDesk encodes too, and a machine-wide reading answers a different question. Verified in both directions on the reference host: False while idle with serverinfo FREE, and True during a live stream where serverinfo still insisted it was idle. ## The warning #23 asked for #23's decomposition established the stall is not fixable here: stopping a seat's Apollo causes no reaction at all; ending the seat's RDP SESSION is the desktop topology change any Apollo on the host reacts to, and a seat is an RDP session. What was wrong was that it happened invisibly -- the operator interrupted someone and had no way to know. SeatManager now logs before teardown when the standalone Apollo is streaming, naming the ~690 ms stall and that it self-recovers. It runs before the lifecycle gate is taken, so it adds no latency under the lock, and it can never block or fail a teardown -- a seat that would not tear down because a status query timed out is a far worse bug than the one it reports. ⛔ Built on the OLD signal this warning would have been silently dead for desktop streaming, which is the common case. That is why the signal was checked before being relied on rather than after. CLAUDE.md's non-destructive coexistence claim now states the exception, and that the cause is session churn rather than a second Apollo.⚠️ Not yet verified: that the warning fires during a real teardown, and stays quiet when nothing is streaming. Both need seat churn and the host was streaming. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
This was referenced Sep 11, 2026
vibesoftwarecoder
added a commit
that referenced
this pull request
Sep 11, 2026
The warning shipped in #50 said the standalone Apollo's stream "will stall for about a second". Verified on the reference host today and that is wrong in the direction that matters -- it makes operators expect something worse than happens. Measured with a client genuinely streaming the console Apollo while a seat was provisioned and torn down: 08:49:23.503 warning fired 08:49:24.661 Apollo: Creating encoder <- 1.2s AFTER the warning 08:49:25.099 Session 8 logged off 08:49:31.996 Apollo: Creating encoder <- 7s after teardown, unexplained The rebuild took 266 ms, against the 690 ms measured on 2026-09-04, and the person streaming DID NOT NOTICE IT AT ALL. So: "hitch for a few hundred milliseconds", not "stall for about a second". CLAUDE.md carries the same correction, with both measurements and the caveat that one user's perception on one LAN does not prove it is always imperceptible. Two other things this run settled, both recorded on #23 rather than here: - Provisioning did NOT cause a rebuild. The session was created at 08:49:09.933 with no encoder activity near it, which supports the original observation in the issue rather than contradicting it. An earlier reading of mine that claimed otherwise was wrong -- corrected by correlating timestamps instead of eyeballing a log tail. - The warning fires BEFORE the stall, by 1.2s, which was the whole point of placing it ahead of the lifecycle gate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
Merged
vibesoftwarecoder
added a commit
that referenced
this pull request
Sep 13, 2026
version.txt 0.6.4 -> 0.6.5, plus the notes the release workflow reads. No code changes -- four merged commits ship: #49 (a streaming seat reported Ready), #50 (a streaming standalone Apollo reported idle), #51 (that warning overstated the stall), #52 (the audit gate failed on a registry outage). ⭐ Three of the four are runtime-verified on the reference host rather than only CI-green: #49 Ready -> Streaming in 6s on connect, back in 3s on disconnect #50 streaming signal correct in BOTH directions, including a live stream the old serverinfo check reported as idle #51 266 ms measured, and the person streaming did not notice it⚠️ And master CI was RED before this. 45f46b0 failed on a 400 from registry.npmjs.org, not on our code -- the same commit had passed its own PR 45 minutes earlier and passed locally afterwards. #52 fixed the gate; the master push on b5feaac is green across all three jobs, checked before cutting rather than assumed. That is worth recording: "the tests pass" is not "master is green", and I reported the first while implying the second. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #23 — and found a live bug on the way.
The signal was wrong
HostApolloInfo.Streamingcame from Apollo'sserverinfoalone:statenot ending inFREE, orcurrentgame != 0. Those describe a launched application, not a client session. Someone streaming the plain desktop — which is what a console Apollo is usually for — leavescurrentgameat 0 andstateatSUNSHINE_SERVER_FREEfor the entire session.Measured 2026-09-11:
So
/api/hosttold the dashboard "not streaming" for the whole 26 minutes the host was streaming.Streamingis now per-process GPU video encode OR the serverinfo signal, read through the same WMI GPU engine countersGpuMonitoralready uses, filtered to the Apollo PID and the videoencode engine. Per process, never the GPU total — RustDesk encodes too, and a machine-wide reading answers a different question.Verified in both directions on the reference host:
Falsewhile idle with serverinfoFREE, andTrueduring a live stream where serverinfo still insisted it was idle.The warning #23 asked for
#23's own decomposition established the stall is not fixable here: stopping a seat's Apollo causes no reaction at all; ending the seat's RDP session is the desktop topology change any Apollo on the host reacts to — and a seat is an RDP session. What was wrong was that it happened invisibly: the operator interrupted someone and had no way to know.
SeatManagernow logs before teardown when the standalone Apollo is streaming, naming the ~690 ms stall and that it self-recovers. It runs before the lifecycle gate is taken, so it adds no latency under the lock, and it can never block or fail a teardown — a seat that would not tear down because a status query timed out is a far worse bug than the one it reports.⛔ Built on the old signal, this warning would have been silently dead for desktop streaming, which is the common case. That is why the signal was checked before being relied on rather than after — the same shape as the launch-on-connect watcher being gated off in #43.
Documentation
CLAUDE.md's non-destructive coexistence claim now states the exception, and that the cause is session churn rather than a second Apollo — the intuitive guess, and this issue's original premise, both wrong.That the warning fires during a real teardown, and stays quiet when nothing is streaming. Both need seat churn, and the host was streaming while this was written. The signal it depends on is verified in both directions; the emission is not.
546 tests passing, 0 failing.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw