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/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".
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:
No consumer branches on "plugin" — the two emissions in tools-catalog.ts are hardcoded string literals, not conditional.
No plugin subsystem is loading tools at runtime (per gutting decisions in prior waves).
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.
Summary
src/gateway/server-methods/tools-catalog.tsstill emitssource: "plugin"on tool catalog entries even though the UI has fully narrowed its types tosource: "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
UI side has already narrowed:
ui/src/ui/types.ts(after gut(ui): remove plugin discriminator from tool catalog types #2522 merged as commit79aa071324):ToolCatalogEntry.source: "core",ToolCatalogGroup.source: "core",pluginId?deleted.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.tsmay 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:"plugin"— the two emissions intools-catalog.tsare hardcoded string literals, not conditional.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 hardcodedsource: "plugin"literals tosource: "core", OR remove thesourcefield 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'ssourceunion toType.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).pluginId, drop it (UI already dropped the field).AC
grep -rn 'source:\s*"plugin"' src/returns zero hitsgrep -rn 'pluginId' src/gateway/returns zero hitssource: Type.Literal("core")(or field removed entirely)pnpm checkgreenpnpm testgreenLIVE=1 pnpm test:livegreen (per CLAUDE.md § PR Submission Workflow)Context
Follow-up to #2522 (
gut(ui): remove plugin discriminator from tool catalog types, merged as #2534 / commit79aa071324). 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-6b79by the/do #2522subprocess, which noted the backend divergence in its PR description for #2534 and recommended a separate follow-up issue.