2e6a4ca200
Installs the dispatch infrastructure for type-driven method resolution without retiring MethodNameCollision yet. The new multi-candidate path is exercised exclusively by 15 unit tests; real workspaces continue producing single-class residuals (candidates: None) and every pre-mq.2 fixture typechecks unchanged. Three new CheckError variants: - AmbiguousMethodResolution (multi-candidate after type-driven filter) - UnknownClass (explicit qualifier names a class not in registry) - NoInstance gains additive candidate_classes field (Vec<String>) Schema/Env additions: - Env.method_to_candidate_classes: BTreeMap<String, BTreeSet<String>> workspace-flat inverse of class_methods, built in build_check_env. - ResidualConstraint.candidates: Option<BTreeSet<String>> — None preserves pre-mq.2 single-class semantics; Some(set) carries the multi-candidate residual that discharge refines. - ResidualConstraint visibility bumped pub(crate) → pub for unit-test crate access. New helpers: - MethodDispatchOutcome enum + pure resolve_method_dispatch implementing the spec's 5-step rule (qualifier → singleton → type-driven filter → constraint-driven filter → Multi for discharge-time refinement). - parse_method_qualifier splits Term::Var.name into (method_name, optional_qualifier_prefix) at the last dot. - RefineOutcome enum + refine_multi_candidate_residual for discharge-time refinement. - resolve_residual_class_for_mono wires the refinement into mono's collect_residuals_ordered residual-to-target mapping. Synth Var-arm class-method branch rewritten via parse_method_qualifier with inner-dot gate (qualifier must be <module>.<Class>; single-dot names fall through to the existing qualified-fn path). Constraint-discharge in check_fn uses expanded (post-superclass- expansion) constraints for the rigid-var path — sounder than raw declared_constraints. Plan-invented format_type_for_display replaced with the existing ailang_core::pretty::type_to_string (one less duplicate). Synth-time declared_constraints: &[] is a deliberate gap documented as known debt — load-bearing only post-mq.3 for the rigid-var fallback (env-plumbing the active fn's constraints into the Var arm is a ~10-line edit slated for mq.3). 9/9 tasks, 539 tests green (was 520 pre-mq.2; +15 mq.2 unit tests + 4 pre-existing). bench/compile_check.py + cross_lang.py clean; bench/check.py 1 regression (latency noise — runtime cannot be touched by a typecheck-side iter).