You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
src/client/api.ts declares its own AttentionPayload, AttentionCardPayload, AttentionSourcePayload, and AttentionDiagnosticPayload interfaces. Since PR #154 those types exist in src/shared/attention.ts, which both the server and the client can import, and PR #157 made the server serve exactly that shape.
They have already drifted. The client's AttentionSourcePayload has no resolved_total, which the route serves; the client's guard ignores the extra field, so nothing breaks today, but the client's type no longer describes the payload it receives. host and dashboard_host are typed string in the client where the shared module has literal unions, so the client cannot benefit from the exhaustiveness the shared types were written to provide.
The duplication existed for a good reason: PR #150 was written in a lane that could not touch shared code, against a contract fixed in its brief, before the route existed. That constraint is gone — the branch is now rebased onto a main carrying both.
Proposed fix
Import the four types from src/shared/attention.ts and delete the local copies. The runtime guards (isAttentionPayload and friends) stay exactly as they are: they are the client's validation boundary and their strictness is deliberate. This is a type-level change only, and the compiler will point at every place where the client's assumptions were looser than the served contract — particularly host and dashboard_host, where narrowing to the literal union may reveal branches that silently accepted any string.
Do this as its own change rather than folding it into a feature PR: the diff should be boring and reviewable as "the client now names the same types the server does".
Evidence
src/client/api.ts — the four local interfaces.
src/shared/attention.ts — the same names, exported, with literal unions for the host fields.
resolved_total is served by the route and absent from the client's source type; the guard ignores unknown fields, which is why this is drift rather than a live defect.
Problem
src/client/api.tsdeclares its ownAttentionPayload,AttentionCardPayload,AttentionSourcePayload, andAttentionDiagnosticPayloadinterfaces. Since PR #154 those types exist insrc/shared/attention.ts, which both the server and the client can import, and PR #157 made the server serve exactly that shape.They have already drifted. The client's
AttentionSourcePayloadhas noresolved_total, which the route serves; the client's guard ignores the extra field, so nothing breaks today, but the client's type no longer describes the payload it receives.hostanddashboard_hostare typedstringin the client where the shared module has literal unions, so the client cannot benefit from the exhaustiveness the shared types were written to provide.The duplication existed for a good reason: PR #150 was written in a lane that could not touch shared code, against a contract fixed in its brief, before the route existed. That constraint is gone — the branch is now rebased onto a
maincarrying both.Proposed fix
Import the four types from
src/shared/attention.tsand delete the local copies. The runtime guards (isAttentionPayloadand friends) stay exactly as they are: they are the client's validation boundary and their strictness is deliberate. This is a type-level change only, and the compiler will point at every place where the client's assumptions were looser than the served contract — particularlyhostanddashboard_host, where narrowing to the literal union may reveal branches that silently accepted any string.Do this as its own change rather than folding it into a feature PR: the diff should be boring and reviewable as "the client now names the same types the server does".
Evidence
src/client/api.ts— the four local interfaces.src/shared/attention.ts— the same names, exported, with literal unions for the host fields.resolved_totalis served by the route and absent from the client's source type; the guard ignores unknown fields, which is why this is drift rather than a live defect.claude-reviewon PR Add the Human Attention view with numbered cards, degraded states, and visibility-aware polling #150 after the rebase, and independently noted by the lane worker during the same rebase.