Skip to content

doctor: share the per-language availability loop with list_supported_languages, and move presentation knowledge into adapters #435

Description

@debugmcpdev

Follow-ups from the #423 doctor command review — two structural improvements deferred from the initial implementation:

1. One shared per-entry availability probe

diagnoseLanguage (src/cli/commands/doctor/diagnose.ts) hand-mirrors the server's handleListSupportedLanguages per-entry loop (src/server.ts: disabled gate → installed gate → getFactory().catch → metadata-over-entry attach preference), with only computeModeAvailability actually shared. Doctor's "can never disagree with the server" guarantee currently rests on manual mirroring: the next change to the server's loop semantics lands in server.ts only and doctor silently diverges — the exact class of drift doctor exists to expose.

Extract one shared per-entry probe (natural home: src/utils/language-availability.ts) consumed by both handleListSupportedLanguages and diagnose, and add a parity test that runs both paths against the same fake registry and asserts identical modes.

2. Adapter-owned doctor presentation

presentLanguage and collectDoctorExtras (src/cli/commands/doctor/presenters.ts) hardcode ~20 stringly-typed validate().details keys plus language→package→export-name mappings in the CLI layer, duck-typed through Partial casts with silent fallbacks. Renaming a details key or an extras export in an adapter package compiles clean and passes all tests while doctor's output silently blanks.

Deeper fix: adapter-owned presentation — typed runtime/backend fields on AdapterMetadata, or an optional IAdapterFactory.describeToolchain() — so an adapter package owns its own doctor row and the CLI stops restating adapter internals. This also removes the "wire the doctor command" step from the new-adapter checklist in CLAUDE.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions