ConverterIntrospector
Reads a converter declaration's ConverterShape from the KSP Resolver: its (S, T) type pair from the MapTypeConverter supertype — found by walking UP the superclass chain, so parameterized-converter bases (the ledger's official recipe: object PriceFormatConverter : FormattedDoubleStringConverter(digits = 2) where the abstract base extends MapTypeConverter<Double, String>) resolve too — and which directions it provides, via function-level detection of the declared overrides (most derived wins) and their @UnsupportedDirection annotations.
Generic-passthrough bases (Base<X> : MapTypeConverter<X, String>) are OUT OF SCOPE: resolving them would require type-argument substitution through arbitrary chains; they produce a guided compile error via logger instead.
Parameters
optional diagnostics sink; null disables the generic-passthrough error (introspection-probe tests construct the introspector without a logger).
Functions
True when converterFqn resolves to ANY class declaration — converter or not. Lets callers distinguish "reference does not resolve" from "resolves but is not a direct MapTypeConverter subtype" when shapeOf returns null.
Returns the ConverterShape for converterFqn, or null when the declaration cannot be resolved or does not extend MapTypeConverter directly. Memoized per instance.
Returns the (S-FQN, T-FQN) pair of declaration's MapTypeConverter<S, T> ancestry, walking up the superclass chain, or null when the declaration never reaches the base (or binds it through an out-of-scope generic passthrough — diagnostic via logger). Public so @KMapperConfig discovery shares the exact same pair resolution.