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:
@ -352,6 +352,43 @@ mod tests {
|
||||
assert!(!factory.supports(&tui));
|
||||
}
|
||||
|
||||
/// §17.3/D7 — **strict coherence**: `AgentProfile::is_selectable` (the menu's
|
||||
/// selection gate) and `StructuredSessionFactory::supports` (the runtime's
|
||||
/// routing gate) must agree on **every** reference profile. If they ever
|
||||
/// diverged, the wizard could offer a profile the runtime cannot drive (or
|
||||
/// hide one it can). Asserting profile-by-profile over the real catalogue —
|
||||
/// including the expected `claude=codex=true`, `gemini=aider=false` truth
|
||||
/// table — means this fails the moment either gate changes without the other.
|
||||
#[tokio::test]
|
||||
async fn supports_and_is_selectable_agree_on_every_reference_profile() {
|
||||
use std::collections::HashMap;
|
||||
let factory = StructuredSessionFactory::new();
|
||||
let profiles = application::reference_profiles();
|
||||
|
||||
let mut expected: HashMap<&str, bool> = HashMap::new();
|
||||
expected.insert("claude", true);
|
||||
expected.insert("codex", true);
|
||||
expected.insert("gemini", false);
|
||||
expected.insert("aider", false);
|
||||
|
||||
assert_eq!(profiles.len(), 4, "catalogue has the four reference profiles");
|
||||
for profile in &profiles {
|
||||
let selectable = profile.is_selectable();
|
||||
assert_eq!(
|
||||
selectable,
|
||||
factory.supports(profile),
|
||||
"is_selectable and supports must agree for `{}`",
|
||||
profile.command
|
||||
);
|
||||
assert_eq!(
|
||||
Some(&selectable),
|
||||
expected.get(profile.command.as_str()),
|
||||
"unexpected selectability for `{}`",
|
||||
profile.command
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn factory_routes_claude_and_codex() {
|
||||
let factory = StructuredSessionFactory::new();
|
||||
|
||||
Reference in New Issue
Block a user