Refactor / justify codebase-wide 'as unknown as' casts (#1690)#1756
Conversation
…1690) Remove the four pre-existing `as unknown as Record<string, unknown>` / `as unknown as MCPServerConfig` casts in core/mcp/serverList.ts: - stripInspectorFields: rewrite as clone + `delete` over INSPECTOR_FIELD_KEYS. Every Inspector-extension key is optional on StoredMCPServer, so the result is still (a subtype of) MCPServerConfig with no cast. - oauth-strip in extractSecretsFromStored: `oauth` is optional, so a plain `delete stripped.oauth` is legal — drop the cast. - mcpConfigToServerEntries: route the one genuinely-needed widening through a single documented `toRecord(value: object)` helper. Taking `object` makes the single `as Record<string, unknown>` legal (no TS2352), so the double cast disappears from the call site. Net: zero `as unknown as` in serverList.ts; the one remaining structural cast lives inside the audited toRecord helper. Behavior-neutral — existing coverage (79 serverList tests) unchanged; full `npm run ci` passes. Closes #1690 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
…sts (#1690) Codebase-wide follow-on to the serverList refactor: audit every `as unknown as` double cast outside tests and either remove it or ensure it carries a justifying comment (the review bar is "no *unjustified* double cast"). Removed (widened via a shared helper or narrowed to a single cast): - Promote the serverList `toRecord(value: object)` widening helper to core/json/jsonUtils.ts and reuse it at core/mcp/node/config.ts (normalize loop), core/mcp/remote/node/server.ts (pino level dispatch), and clients/web/src/App.tsx (window global lookup). - inspectorClient.rawWireRequest: type the frame as `JSONRPCRequest` and narrow only `params` with a single structural cast (the SDK's `_meta`-typed params is what blocked direct assignment). - toolOutputValidation: SDK `outputSchema` → `JsonSchemaType` is a single cast. - test-server-fixtures: the optional `task` handle is reachable with a single cast (target field is optional). Justified in place (genuinely unavoidable — private SDK internals, partial interface stubs, third-party/nominal bridges): the inspectorClient private-map accesses, resourceContext + tokenAuthProvider partial `OAuthClientProvider` stubs, the ext-apps peer bridge, modern/legacy `_requestHandlers` bypasses, and the happy-dom `matchMedia` test mock. Behavior-neutral. Full `npm run ci` passes (validate, ≥90 coverage gate, smoke, Storybook). Refs #1690 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
@claude review |
|
Claude finished @cliffhall's task in 2m 12s —— View job Review: Refactor / justify
|
…flow noise (#1690) - test-servers/src/modern-tasks.ts: add an inline justification above the `_requestHandlers` double cast, mirroring the sibling in composable-test-server.ts (was leaning on the function JSDoc only). - Annotate the partial-`AppBridge` mock double casts in the story fixtures (AppsScreen ×2, AppRenderer, InspectorView) so no non-test-file double cast is unjustified. - inspectorClient.ts: revert unrelated Prettier reflow hunks (protocolVersion, task-content array, timeout-reject wrap, reconnect guard) so the diff is the single rawWireRequest cast change only. Behavior-neutral (comment/format-only). `npm run ci` green apart from a known flaky redaction test whose assertion collided with a random request id. Refs #1690 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
Thanks for the thorough pass! Addressed all three observations in
Note: @claude review |
|
Claude finished @cliffhall's task in 1m 46s —— View job Re-review: nit fixes in
|
The reflow reverts in cc187ea were silently undone by a `prettier --write` I ran on the same file right after, so the four Prettier-only hunks from 6a3afa4 were still in the diff (caught in re-review). Revert them for real now — and without re-running Prettier on the file: - core/mcp/inspectorClient.ts: restore the protocolVersion line, task-content array, timeout-reject call, and reconnect guard to their origin/v2/main form, so the file's diff is only the single rawWireRequest cast change. - test-servers/src/modern-tasks.ts: restore the ModernTaskStatus union to its one-line form (the leading-`|` reflow was also Prettier churn), leaving only the new `_requestHandlers` justification comment. Formatting-only; `npm run validate` green. Refs #1690 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5
|
Good catch — you're right, and the cause was self-inflicted: my reflow reverts in Fixed for real in
Agreed on the flaky @claude review |
|
Claude finished @cliffhall's task in 40s —— View job Re-review: reflow revert in
|
Closes #1690
What
Removes or justifies every
as unknown asdouble cast in non-test source. Started as the scopedserverList.tscleanup flagged in the SDK v2 migration review of #1688, then expanded (per maintainer request) to a codebase-wide sweep applying theAGENTS.mdbar: no unjustifiedas unknown as.Removed
serverList.ts(the original four):stripInspectorFields(input + return casts)deleteoverINSPECTOR_FIELD_KEYS; every extension key is optional onStoredMCPServer, so the result is still a subtype ofMCPServerConfig— no castextractSecretsFromStoreddelete stripped.oauth(oauthis optional)mcpConfigToServerEntriestoRecord()widening helperShared helper —
toRecord(value: object): Record<string, unknown>promoted tocore/json/jsonUtils.ts. Taking the argument asobjectmakes the singleas Record<string, unknown>legal (no TS2352), so the double cast leaves the call sites. Reused at:core/mcp/node/config.ts— thenormalizeServerTypeloopcore/mcp/remote/node/server.ts— pino log-level dispatchclients/web/src/App.tsx—windowglobal token lookupSingle-cast narrowings:
inspectorClient.rawWireRequest— type the frame asJSONRPCRequest, narrow onlyparams(the SDK's_meta-typed params blocked direct assignment)toolOutputValidation—outputSchema as JsonSchemaTypetest-server-fixtures(×2) — the optionaltaskhandle needs only a single castJustified in place
Genuinely unavoidable (private SDK internals / partial interface stubs / nominal bridges), each now commented: the
inspectorClientprivate-map accesses and task-result gaps,resourceContext+tokenAuthProviderpartialOAuthClientProviderstubs, the ext-apps v1/v2 peer bridge, the modern/legacy_requestHandlersbypasses in the test servers, and the happy-dommatchMediatest mock.Verification
Behavior-neutral. Existing 79
serverListtests pass unchanged; fullnpm run cipasses (validate, the ≥90 per-file coverage gate, smoke, 456 Storybook tests).🤖 Generated with Claude Code
https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5