Skip to content

TASK-1622 — Pour / Contre : modèles FREE vérifiés / PAYANTS approuvés - #623

Merged
cslucki merged 11 commits into
developfrom
TASK-1622-pour-contre-modeles-free-verifies-payants-approuves
Sep 23, 2026
Merged

cslucki merged 11 commits into
developfrom
TASK-1622-pour-contre-modeles-free-verifies-payants-approuves

Conversation

@cslucki

@cslucki cslucki commented Sep 23, 2026

Copy link
Copy Markdown
Owner

TASK-1622

Le SuperAdmin peut désormais choisir, pour chaque rôle séparément, entre
un modèle Gratuit vérifié (mécanisme TASK-1617 inchangé) et un modèle
Payant approuvé. Le mode payant est livré comme capacité
administrable
: aucun modèle payant ne devient le défaut dans cette TASK
(arbitrage MASTER).

Le contrat payant — quatre marches, toutes fail-closed

Un modèle payant n'est utilisable que s'il est approuvé (auteur + date),
dans la shortlist (ai.multi_ai.paid_model_shortlist — décision de
code, auditée), tarifé au relevé statique (entrée exacte, non-free — un
tarif générique de provider ne vaut pas approbation d'un modèle) et connu
du catalogue OpenRouter. Catalogue illisible = refus. Aucun repli, dans
aucun sens : ni payant → gratuit, ni gratuit → payant.

  • model_type + approved_at/approved_by (FK déclarée au
    UserDataLifecycleRegistry) ; timestamp et non timestampTz.
  • entryFor() ignore les lignes payantes : un payant n'est jamais chiffré
    0 par la source dynamique, même avec une preuve de gratuité forgée.
  • UI par rôle : type, tarifs par option, badges, ligne d'audit ; une
    entrée de shortlist sans tarif reste visible mais inactivable.

Correctif de ledger, borné

LoopMultiAiOrchestrator écrivait status: 'completed' — un hapax : le
domaine // success | failed est déclaré par la migration créatrice du
ledger (T1220), un mois avant ce moteur, et 17 sites d'appel sur 18
l'emploient. Ces lignes n'entraient dans aucun filtre status = success
(quota des coûts inconnus, compteurs). Tolérable à coût 0 ; inacceptable
avant d'autoriser la dépense payante.

Les 132 lignes historiques completed ne sont pas backfillées (décision
MASTER) : valeur morte, lue par aucun consommateur ; les convertir
injecterait 3 opérations dans le quota du mois en cours. ai_interactions
n'est pas touchée.

Tests

TASK1622PaidModelApprovalTest 24 verts (78 assertions) · voisins par
contrat 253 verts, 0 rouge · PostgreSQL 141 verts · 6 sabotages
rouges
, dont deux tests corrigés d'un vert pour la mauvaise raison.
Benchmark réel : 66 appels, 0,0136 $, zéro retry — rapport au TASK file.
Recette admin réelle (Chrome) sur /admin/loop-plugins.

Configuration de référence conservée : inclusionai/ling-3.0-flash-vl:free
POUR et CONTRE.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3

Cyril and others added 3 commits September 22, 2026 22:20
…fie (TASK-1622)

model_type + approved_at/approved_by (FK declaree au lifecycle registry) ;
assignPaid a 4 marches fail-closed (shortlist config, tarif statique exact
non-free via AiPricingCatalog::staticRateFor, slug connu du catalogue) ;
garde d'execution branche payante sans aucun repli ; entryFor ignore les
lignes payantes (jamais chiffrees 0, meme forgees) ; UI admin par role
(type, tarifs par option, badges, audit) ; statut ledger 'completed' ->
STATUS_SUCCESS (les lignes du moteur entrent enfin dans les releves —
requis avant toute depense payante). 19 verts neufs + 208 voisins +
122 en PG + 4 sabotages rouges (dont 1 test corrige d'un vert pour la
mauvaise raison).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
… semantique (TASK-1622)

Audit MASTER du changement completed -> success : success est bien le
domaine canonique du provider (migration creatrice T1220, 17 writers sur
18) ; completed etait un hapax de ce moteur, 132 lignes d'un seul jour,
lu par aucun consommateur. Pas de lecture backward-compatible : admettre
les 29 lignes a cout inconnu injecterait 3 operations au quota du mois.

Retire le changement COLLATERAL sur ai_interactions (autre table, autre
vocabulaire) : un seul des trois chemins de sortie avait ete change.
Commentaire reecrit sur la mesure (103 cout connu 0 + 29 cout INCONNU,
dont 10 appels payants de T1621 qui n'ont jamais consomme le quota).

4 tests neufs : domaine canonique, non-contamination des traces (les 3
sorties), hors-sujet paye et compte comme tel, et garde TASK-1624 sur
CREDITABLE_PROCESSES. 23 verts + 193 voisins + 105 PG + 6 sabotages.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
… ledger (TASK-1622)

Pin de semantique demande par MASTER : les TROIS sorties du moteur qui
ecrivent une ligne (succes, abstention, reponse vide) sont exercees, et
l'ensemble des statuts ecrits doit etre exactement [failed, success].
La colonne est un varchar(10) sans enum : ce test est la seule barriere.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
@cslucki cslucki added the validation:sensitive TASK-1150 : charge CI complete obligatoire (auth/tenant/migration/securite) label Sep 23, 2026
Cyril and others added 4 commits September 23, 2026 04:42
…ssigner le camp (TASK-1622)

Decision MASTER du 23/09. La v3 posait l'assignation du camp en TETE :
un modele applique alors une etiquette POUR/CONTRE puis cherche ce
qu'elle peut vouloir dire. v4 impose un ORDRE en 5 etapes — comprendre,
decider s'il y a deux camps, s'abstenir si non, recevoir son camp,
VERIFIER chaque argument avant d'ecrire.

CHANGEMENT DU SOCLE COMMUN, identique pour tous les modeles : aucune
logique par modele ni par provider (doctrine « un contrat commun,
plusieurs candidats »). Les bornes de forme sont conservees a
l'identique. AiPromptSeeder n'ecrase jamais : v4 est une version NEUVE,
v3 desactivee par la regle du plus haut actif.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
Les trois tests qui epinglaient le TEXTE v3 suivent la reecriture : les
invariants de camp survivent, seule leur formulation a bouge. Pin NEUF et
plus solide sur le point meme de la v4 — l'ORDRE des etapes se mesure par
une POSITION (comprendre < s'abstenir < assigner < verifier), pas par une
phrase. Sabotage verifie : etape de comprehension deplacee -> rouge.

Banc v4 rejoue (66 appels, 0,0145 USD cumule sur les deux bancs, aucun
retry) : aucun candidat n'atteint 6/6, la configuration de reference ne
change pas. Messages de recette nettoyes (0 restant).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
Socle commun v5 : COMPRENDRE -> CADRER -> ASSIGNER -> VERIFIER ->
DEFENDRE. Hypothese MASTER : une sequence POSITIVE conduit mieux qu'un
empilement de defenses. Les v3/v4 avaient grossi par sedimentation —
chaque defaut de recette ajoutait son garde-fou, si bien que le modele
lisait une liste d'interdits avant de savoir ce qu'on attendait de lui.
v5 dit la meme chose en cinq gestes affirmatifs. Aucun contenu neuf :
une reformulation. Plus la contrainte de langue (meme langue que la
question).

Socle COMMUN, identique pour tous les modeles. v3 et v4 CONSERVEES en
base (desactivees) et dans le seeder : revenir en arriere est un
changement de is_active, jamais une reecriture.

Pins de tests migres sur les invariants v5 — le camp n'est pas choisi,
referent A/B, defendre et pas seulement attaquer — et l'ORDRE des cinq
etapes reste mesure par POSITION, pas par une phrase.

Baseline avant ce commit : 1bfd609

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
…res mesure (TASK-1622)

ARBITRAGE MASTER 23/09 05h30. v5 degrade franchement NOT_APPLICABLE :
4/6 modeles s'abstenaient correctement en v3, 3/6 en v4, 1/6 en v5. La
sequence positive est plus elegante, mais en faisant de l'abstention un
sous-cas du cadrage, elle lui retire le poids qu'elle avait comme regle
autonome.

v4 retenue : ling sans regression demontree, nova 2/6 -> 5/6, qwen
4/6 -> 5/6, NOT_APPLICABLE nettement meilleur qu'en v5.

Le seeder pose is_active = false sur l'entree v5 — sans quoi une base
neuve (CI, nouvel environnement) aurait reactive le socle rejete, la
regle du seeder etant « la version ACTIVE la plus haute gagne ».
Idempotence verifiee par rejeu. Le texte de v5 est conserve avec son
motif de rejet : une mesure negative est un resultat. Pins de tests
restaures sur les invariants v4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
@cslucki
cslucki force-pushed the TASK-1622-pour-contre-modeles-free-verifies-payants-approuves branch from 799be9f to 87bd78c Compare September 23, 2026 03:34
Cyril and others added 4 commits September 23, 2026 05:44
DEFAUT REEL constate en recette (Cyril, 23/09) : « PC ou Mac que
choisir ? » rend NOT_APPLICABLE alors que le membre nomme deux
alternatives. Mesure : 3/3 essais, POUR s'abstient ; la file etant
annulee des la premiere abstention, CONTRE n'est jamais lance et le
membre ne lit que la notice neutre. Trace : 6 abstentions recentes,
toutes du role aperio.

CAUSE mesuree : v3 traitait la question 3/3. Ce n'est pas le modele qui
a change, c'est le socle. Piste de la virgule ECARTEE par la mesure
(« PC ou Mac, que choisir ? » echoue aussi). Reste : le modele juge que
PC et Mac ne sont pas nettement opposables, et l'etape de cadrage de v4
lui donne la permission de s'arreter la.

CORRECTION : la reconnaissance d'une comparaison A/B explicite PRECEDE
desormais l'abstention, qui devient le DERNIER recours ; le socle dit
de respecter le cadre pose par le membre meme si les alternatives se
chevauchent techniquement ou sont nommees familierement. Aucun cas
special PC/Mac : la regle ne nomme aucun produit. v4 conservee.

Pins migres sur les invariants v6, dont l'ORDRE des etapes mesure par
position : comparaison A/B AVANT abstention.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
…ABLE (TASK-1622)

Checkpoint avant la passe « aider a reformuler ». Baseline de cette
passe : socle v6 (A/B avant abstention), HEAD v6 =
35db2a6.

TASK repasse IN_PROGRESS / LOCKED — le TASK file (gitignore) porte le
detail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
…TASK-1622)

Quand « Pour / Contre » conclut qu'une question n'ouvre aucun debat, le
MEME appel provider propose desormais une reformulation exploitable. Le
membre clique, le texte arrive dans le composeur, il le modifie s'il veut
et l'envoie LUI-MEME : l'IA propose, l'humain garde le dernier geste.

Audit avant d'inventer. Le jeton [[SUGGESTION]] etend le seul idiome de
contrat de prompt du depot et reste RETRO-COMPATIBLE (str_contains sur le
marqueur d'abstention inchange : les socles v3-v6 s'abstiennent
exactement comme avant). Canal DEDIE sur AssistantOutcome plutot que
followUps : un approfondissement prolonge une reponse, une reformulation
la remplace. useSuggestion() ne prend AUCUN parametre — le serveur relit
sa propre suggestion, rien ne voyage depuis le client.

Piege evite grace a l'audit : le composeur est en wire:model differe et
son hasText pilote le bouton d'envoi ; sans l'evenement composer-filled,
le membre aurait lu sa question sans pouvoir l'envoyer.

Socle v7 derive de v6 (v6 conservee). Il interdit d'inventer un produit
que le membre n'a pas nomme : pas de suggestion fidele possible = pas de
suggestion, et l'ecran demande une precision.

41 verts (+5), 169 avec les voisins, 65 en PG, 3 sabotages rouges.
Micro-recette reelle Ling : 5 cas sur 6 conformes ; le cas « Quelle est
la difference entre X et Y ? » declenche encore un debat — rapporte a
MASTER, non corrige seul (le corriger risque de ramener le defaut
« PC ou Mac » que cette passe vient de fermer).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
…622)

« Quelle est la difference entre PC et Mac ? » declenchait un debat.
L'etape 2 de v6/v7 ne posait qu'une question — deux alternatives sont-elles
nommees ? — et deux noms suffisaient a fabriquer deux camps. Ce n'etait pas
un accident : cette detection agressive est ce qui avait repare « PC ou Mac
que choisir ? ». Le defaut etait le prix de la reparation.

v8 (derivee de v7, v7 conservee) pose DEUX conditions conjointes a l'etape
2 : deux alternatives nommees ET une intention de les departager. Les formes
informatives sont nommees explicitement, sans quoi la regle serait restee
abstraite.

Le cas ecarte ne tombe pas dans le vide : l'etape 4 reformule une question
de COMPARAISON en question de CHOIX entre les deux memes noms, dans l'ordre
ou le membre les a donnes — rien n'est invente. Garde soeur indispensable :
une question qui cherche a FAIRE COEXISTER les deux ne doit pas se voir
proposer de les departager, le membre possede deja les deux ; sans elle, la
reformulation aurait casse « Comment faire communiquer un PC et un Mac ? ».

Aucun cas special PC/Mac : la regle ne nomme aucun produit, et un test
l'epingle.

Recette reelle Ling, 6 cas sur 6 conformes, « PC ou Mac » intact dans les
deux ordres. 171 verts, 136 en PG, 2 sabotages rouges.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
@cslucki
cslucki merged commit d0c47c2 into develop Sep 23, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

validation:sensitive TASK-1150 : charge CI complete obligatoire (auth/tenant/migration/securite)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant