In v1.3.3-beta.4, `reset_on_idle_mins` could be configured correctly but
the idle session rotation never fired. The root cause is that
`Session.Unlock()` bumps `UpdatedAt` on every heartbeat execution and
unsolicited agent response, so the idle check in
`maybeAutoResetSessionOnIdle` always saw a fresh timestamp and never
rotated the session.
Add `Session.LastUserActivity`, a separate timestamp that is only set
via `TouchUserActivity()` when the engine processes a real incoming user
message (after the idle-reset check). The idle check now prefers
`LastUserActivity` and falls back to `UpdatedAt` for sessions created
before this field was introduced. The previous behaviour is preserved
on disk because the new field is `omitempty`.
A new regression test (`TestHandleMessage_AutoResetOnIdle_FiresWhenHeartbeatBumpedUpdatedAt`)
stubs a stale `LastUserActivity`, simulates a heartbeat by calling
`Unlock()`, and verifies that the next user message still triggers
idle rotation.
Fixes#1221
Co-authored-by: Claude <claude@anthropic.com>