Streaming replies change height many times, not once. Images, fonts, and status elements can also reflow after a message is inserted, so a single `scrollTop` assignment is unreliable.
Always forcing the bottom is worse: it yanks users away from history they intentionally scrolled up to read. The interface needs to remember whether following was wanted before the update.
What was actually going wrong
The log treated every DOM change as permission to override the user's scroll position.
What I tried
- Scrolling once immediately after appending a bubble
- Calling smooth scroll on every streamed token
- Always pinning the container regardless of user position
A near-bottom check controls whether updates follow, with a deferred final scroll after content settles.
Why it worked
The code preserves user intent and still absorbs late layout changes.
Good auto-scroll is conditional state management, not a repeated command.
Where EACI uses this today
Main chat follows active conversation without trapping users at the bottom.
This journal covers real engineering on EACI Companion / The Veil. Companions include Caelum, Chad, Natalia, Atreus, Luna, Roxy, and Cael. Journal articles stay family-safe in content. See Privacy and Ethics.