--- name: model-catalogue-compat-cadrage description: Frontières hexagonales, ports, DTO, fallback et matrice de compatibilité versionnée pour l'évolution du catalogue de modèles des profils structurés Codex/Claude. metadata: type: reference --- Évolution de `ListClaudeModels`/`ListCodexModels` (catalogue statique `application/src/agent/model_catalogue.rs`) vers un catalogue enrichi par compatibilité CLI. **Décisions tranchées :** - JAMAIS scraper les TUI `/model`, JAMAIS exécuter les CLIs pour énumérer les modèles. Seule exécution CLI autorisée : ` --version` (pattern existant `infrastructure/runtime::detection_spec` + port `ProcessSpawner`). Saisie libre toujours ouverte. - 3 sources non bloquantes à dégradation indépendante : API provider `/v1/models` (best-effort, uniquement si clé env/SecretStore présente, sinon skip), catalogue statique seed, matrice de compat. **Hexagonal :** - Domaine (pur) : VO `CliVersion` (Ord), enum `ModelCompatibility {Compatible|Unknown|LikelyTooRecent}` (miroir des 3 états produit), VO `CompatibilityMatrix` (forme seule), fonction pure `evaluate_compatibility(matrix, adapter, model_id, Option)` — version None ⇒ Unknown, modèle absent ⇒ Unknown, min<=ver ⇒ Compatible, min>ver ⇒ LikelyTooRecent. - Nouveaux ports : `CliVersionReader`, `ProviderModelCatalogue` (Ok(vec![]) si pas de clé), `CompatibilityMatrixSource` (infaillible). - Application : use case unique `ResolveModelCatalogue{adapter}` async, jamais de hard-error sur échec source (warnings + fallback). `ListClaude/CodexModels` deviennent des façades. - Infra : `ProcessCliVersionReader`, `HttpProviderModelCatalogue` (reqwest), `EmbeddedCompatibilityMatrix`. **Matrice de compat = DONNÉE, pas code** : JSON versionné maintenu dans IdeA, bundlé via `include_str!` (seed infaillible) + override optionnel `app_data_dir/IdeA/model-compat.json`. Ajouter un modèle = éditer le JSON, zéro code (Open/Closed). **DTO (rupture front)** : `ProfileModelCatalogDto` passe de `transparent Vec` à `{ models:[{...,compatibility,source}], cliVersion:string|null, warnings:string[] }`. Répercuter ports TS + 2 adapters + mock + ProfilesSettings. **Découpage** : B1 domaine pur, B2 use case ports mockés, B3 infra ; F1 contrat, F2 ProfilesSettings 3 badges. UX passe avant F2 (libellés des 3 états, warnings, cliVersion null). **Point ouvert produit** : récup clé provider — proposé best-effort sur clé env/SecretStore existante, pas de prompt dédié.