chore(web): address Copilot review on #2128

Seven of the eight comments, plus the three suppressed ones (the same
double-cast class):

- Narrow the toast hooks to `InspectorClientEventSource`, the client's
  typed event-listener surface. A bare `EventTarget` cannot satisfy it
  (its listener takes an `Event`, the typed one a `TypedEventGeneric`
  with `detail`), so both tests now construct a real
  `InspectorClientEventTarget` and dispatch through `dispatchTypedEvent`
  rather than casting a stand-in. That failed to compile immediately and
  caught two bad fixtures: `task()` was a `Pick<Task, "status">` where
  the event map wants a full `Task`, and `toolCallTaskUpdated` was
  dispatched with no `task` at all.
- Narrow `useExportActions`'s three store parameters to the single
  clearing method each handler calls, so the test doubles are
  structurally checked instead of cast away.
- Build real `MessageEntry` fixtures (`timestamp` is a `Date`, not `0`),
  removing four more double casts.
- Fix a tautological assertion in useTabUiState.test: it compared a
  callback to itself, so it held however the identity changed. Every
  callback is now captured before the update and compared to those
  references.
- Reword `resetTabUiState`'s doc: `exhaustive-deps` cannot infer
  stability across a hook boundary, so the dependency IS named — the
  stability buys no churn, not omission.
- Justify the one remaining double cast in place, per the type-safety
  rule.

`useProgressToasts` still returns `void` rather than an object,
deliberately: it has nothing to return, and `{}` would imply an API that
is not there. Noted on the PR as the one deviation from #2128's
"returns one object" criterion.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-26 19:58:02 -04:00
commit edac58e304

View file

@ -44,9 +44,12 @@ export interface TabUiStateResult {
togglePinProtocol: (id: string) => void;
/**
* Reset every screen's UI object and the pin set to their empty defaults.
* Stable, so the session-reset callback that drives it needs no dependency
* on this hook. Deliberately leaves `activeTab` alone: the tab the user is
* on is shell state, reset separately on an *explicit* disconnect.
* Its identity never changes, so naming it in the dependency array of the
* session-reset callback that drives it — which `exhaustive-deps` requires,
* since the rule cannot infer stability across a custom-hook boundary —
* costs that callback no churn. Deliberately leaves `activeTab` alone: the
* tab the user is on is shell state, reset separately on an *explicit*
* disconnect.
*/
resetTabUiState: () => void;
}