Only appLeave was missing the super call - which might explain the ghost connections. :)
I'm joining people into the room from the server side using IConnection.connect(IScope scope, Object[] params).
If the scope does not exist, it is being created with IScope.createChildScope(String name). This part seems to work, because roomStart is being logged.
The next step in my application is a roomJoin(IClient client, IScope scope) override, which worked perfectly up to 4572, but doesn't get called in 4604 anymore.
There has been some scope work in between the two. Maybe the way I'm connecting people to the new scope is flawed and should have never worked, or maybe something in red5 is broken. Dunno. :)
Only appConnect, appLeave, roomJoin, and roomLeave are overridden.