feat(agent): menu de profils restreint Claude/Codex + retrait custom (D7) — §17

Dernier lot de §17 : seuls les profils pilotables en mode structuré sont
proposés à la sélection/création.

- domain : AgentProfile::is_selectable() = structured_adapter.is_some(),
  source unique de vérité du prédicat.
- infrastructure : AgentSessionFactory::supports délègue à is_selectable
  (supports et is_selectable ne peuvent plus diverger).
- application : selectable_reference_profiles() = reference_profiles()
  filtré ; ReferenceProfiles et FirstRunState exposent la liste filtrée
  (Claude/Codex). reference_profiles() brut reste à 4 (data intacte) ⇒
  un agent Gemini/Aider/custom legacy déjà configuré continue de tourner.
- frontend : bloc AddCustomProfile retiré du wizard first-run, action
  addCustom retirée du viewmodel ; wizard n'affiche que la liste filtrée.

Tests (QA) : is_selectable (table de vérité), cohérence stricte
is_selectable<->supports, liste exposée=2 / data brute=4, garde
anti-régression Vitest sur l'absence du bloc custom — validées par
mutation. cargo test --workspace : 820 passed. npx vitest run : 344 passed.

§17 COMPLET (D0->D7). Suivi restant : D6b (surfacer reply dans le writer
wire .response.json pour la délégation par protocole fichier).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 23:57:51 +02:00
parent dd1194abe8
commit 6de4e5a6e0
15 changed files with 324 additions and 245 deletions

View File

@ -569,8 +569,13 @@ pub async fn first_run_state(state: State<'_, AppState>) -> Result<FirstRunState
.map_err(ErrorDto::from)
}
/// `reference_profiles` — the pre-filled, editable reference catalogue
/// (Claude/Codex/Gemini/Aider).
/// `reference_profiles` — the pre-filled, editable reference catalogue offered to
/// agent creation/selection.
///
/// Restricted to the **selectable** profiles (§17.3, lot D7): only profiles
/// drivable in structured mode (today Claude + Codex) are returned. Gemini/Aider
/// stay in the catalogue data but are not proposed, and there is no custom-profile
/// entry. Persistence/editing of pre-existing (legacy) profiles is unaffected.
///
/// # Errors
/// Returns an [`ErrorDto`] (never in practice; the catalogue is in-memory).
@ -651,8 +656,15 @@ pub async fn delete_profile(
.map_err(ErrorDto::from)
}
/// `configure_profiles` — persist the batch of chosen/edited/custom profiles,
/// closing the first run.
/// `configure_profiles` — persist the batch of chosen/edited profiles, closing
/// the first run.
///
/// The selection surface offered upstream is already restricted to selectable
/// profiles (§17.3, D7), so the wizard sends only structured-drivable profiles
/// and no arbitrary custom command. This command itself stays permissive on
/// purpose: it must keep persisting any profile shape so a project with a
/// pre-existing Gemini/Aider/custom **legacy** profile remains editable and
/// runnable (we restrict creation, not the existing).
///
/// # Errors
/// Returns an [`ErrorDto`] (`STORE` on profiles I/O failure).