- `useEmaIdpLoginState`: the effect-triggered `refresh()` was discarded with
`void`, but it does not own its failures — `getEmaIdpLoginState` awaits
`storage.getIdpSession`, which rejects when the backend is unreachable.
Terminate with `.catch()` and leave `loginState` untouched, as `logout`
already does. Covered by a new test that also asserts no unhandled
rejection escapes.
- Correct the history: the plugin was *client-local*, declared by both
`clients/web` and `clients/tui`. The root could reach neither, since Node
resolution walks up rather than down — that, not web-exclusivity, is why
`core/react/` went unlinted.
- Correct the enforcement claim: `clients/tui` registers the plugin but
deliberately enables only `rules-of-hooks` and `exhaustive-deps`, so
`set-state-in-effect` and `refs` hold for `clients/web` and `core/react/`
only. Says so in AGENTS.md and in the Copilot mirror, which would
otherwise have reviewers cite rules the TUI gate does not run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev
Signed-off-by: cliffhall <cliff@futurescale.com>