Skip to content

gut(backend): narrow tool catalog source discriminator to "core" #2537

@alexey-pelykh

Description

@alexey-pelykh

Summary

src/gateway/server-methods/tools-catalog.ts still emits source: "plugin" on tool catalog entries even though the UI has fully narrowed its types to source: "core" (see #2522). The backend and UI type systems disagree on the discriminator, and the plugin subsystem has been gutted per CLAUDE.md § Fork Context "What's being removed".

Evidence

src/gateway/server-methods/tools-catalog.ts:99:        source: "plugin",
src/gateway/server-methods/tools-catalog.ts:110:      source: "plugin",

UI side has already narrowed:

If the UI ever type-validated catalog responses against the declared shape, the backend's "plugin" emissions would fail narrowing. Current UI deserialization is untyped cast — so the divergence is a latent trap that will bite the first time schema validation is introduced.

The protocol schema at src/gateway/protocol/schema/agents-tools.ts may still declare the "core" | "plugin" union (flagged by the #2522 subprocess — verify during implementation).

Why this is safe

Narrowing backend emission to always "core" is safe because:

  1. No consumer branches on "plugin" — the two emissions in tools-catalog.ts are hardcoded string literals, not conditional.
  2. No plugin subsystem is loading tools at runtime (per gutting decisions in prior waves).
  3. The UI has already narrowed (gut(ui): remove plugin discriminator from tool catalog types #2522); backend narrowing closes the type divergence.

If discovery reveals "plugin" is emitted via a code path tied to an active feature (unlikely given gutting history), surface and coordinate before narrowing.

Changes

  • src/gateway/server-methods/tools-catalog.ts:99,110 — change both hardcoded source: "plugin" literals to source: "core", OR remove the source field entirely if narrowing the protocol schema to a single-value enum makes the field redundant.
  • src/gateway/protocol/schema/agents-tools.ts — narrow the TypeBox schema's source union to Type.Literal("core") (or drop if narrowed to a single value). Verify the exact line range during implementation (flagged as lines ~200,219 by the gut(ui): remove plugin discriminator from tool catalog types #2522 UI subprocess but not re-verified here).
  • If protocol schema still advertises pluginId, drop it (UI already dropped the field).
  • Run the protocol-schema codegen (if any) and commit regenerated artifacts.

AC

  • grep -rn 'source:\s*"plugin"' src/ returns zero hits
  • grep -rn 'pluginId' src/gateway/ returns zero hits
  • Protocol schema emits source: Type.Literal("core") (or field removed entirely)
  • pnpm check green
  • pnpm test green
  • If middleware/runtime code changed: LIVE=1 pnpm test:live green (per CLAUDE.md § PR Submission Workflow)

Context

Follow-up to #2522 (gut(ui): remove plugin discriminator from tool catalog types, merged as #2534 / commit 79aa071324). The UI narrowing was deliberately scoped to the UI type system because backend coordination was out of scope for that PR. This issue tracks the backend half of the same cleanup.

Surfaced during batch 20260424-6b79 by the /do #2522 subprocess, which noted the backend divergence in its PR description for #2534 and recommended a separate follow-up issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    gutRemoving dead upstream subsystems

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions