Skip to content

TASK-1616 — Activation du plugin « 3 assistants IA » dans une Boucle + configuration Aperio/Traverse/Limen - #617

Merged
cslucki merged 2 commits into
developfrom
TASK-1616-activation-du-plugin-3-assistants-ia-dans-une-boucle-et-configuration-aperio-traverse-limen
Sep 21, 2026
Merged

cslucki merged 2 commits into
developfrom
TASK-1616-activation-du-plugin-3-assistants-ia-dans-une-boucle-et-configuration-aperio-traverse-limen

Conversation

@cslucki

@cslucki cslucki commented Sep 21, 2026

Copy link
Copy Markdown
Owner

SLICE B — le plugin s'active dans une Boucle, et ses trois assistants se règlent

Les deux maillons suivants de la chaîne posée par SLICE A (TASK-1614) :

catalogue plateforme   config/loop_plugins.php          SLICE A
        ↓
disponibilité Organization   organization_loop_plugins  SLICE A
        ↓
activation dans une Boucle   loop_plugins               ← ICI
        ↓
configuration des 3 assistants   loop_ai_assistants     ← ICI
        ↓
usage dans ChatLoop                                     SLICE E

Zéro appel provider.


La décision centrale : le plugin n'est PAS une LoopCard

Le bloc « Actions de ChatLoop » est piloté par les Cards de placement
chat_action — « Résumé IA » est core.ai_summary. Modéliser le plugin ainsi
aurait semblé naturel, et aurait été faux.

LoopPresetConfigurator::canConfigure() est propriétaire-only, avec le
commentaire explicite « un animateur anime, il ne recompose pas ». Et la
matrice mesurée, pas lue dans la doc :

owner       : loops.manage_cards = NON
facilitator : loops.manage_cards = NON
member      : loops.manage_cards = NON

loops.manage_cards a été retirée de l'owner par TASK-1083, au motif écrit que
« la matrice annonçait un droit que l'interface ne donnait pas ».

Passer par la Card imposait donc de choisir entre exclure le facilitator
(contre le CDC §5) et percer une doctrine posée exprès. Le plugin garde son
propre état, rendu à côté de « Résumé IA », et son propre droit.

loop_plugins.configure — nécessaire, pas inventé

Absent du dépôt ; le CDC §5 le nommait déjà. Déclaré dans
config/loop_permissions.php, accordé à owner + facilitator dans
role_defaults. SuperAdmin et Admin d'Organization l'obtiennent par les étapes
3 et 4 du résolveur, jamais par ce socle. Le membre tombe en refus à l'étape 11.

Aucun droit Cards n'est élargi — un test le verrouille explicitement.

Le hard gate vit dans le service, pas dans l'écran

Cacher un bouton n'a jamais empêché un POST. Chaque lecture et chaque écriture
reconfronte la disponibilité de l'Organization de la Boucle — jamais celle
de l'utilisateur, puisqu'un SuperAdmin agit depuis /admin, hors du tenant.
Retirer l'autorisation éteint toutes les Boucles de l'Organization d'un coup,
sans réécrire une seule ligne.

Et « pas autorisé » n'est pas « éteint » : l'écran rend alors un tableau vide,
le plugin en est absent. Un plugin visible suggère un geste possible.

Écart, pas copie

Une ligne loop_ai_assistants existe seulement là où la Boucle s'est écartée
du catalogue. Une posture identique au défaut n'est pas stockée, et vider un
champ supprime l'écart
au lieu de recopier le défaut — sinon la Boucle
figerait le texte du jour et cesserait de suivre le produit. Convention de
loop_type_settings.

Les postures survivent à l'extinction, dans la Boucle comme dans
l'Organization : rallumer rend ses réglages, il ne les redemande pas.


Tests — 27/27, et les deux gardes sont mesurées

Sabotage 1isAvailableFor() ne consulte plus la disponibilité :

⨯ le plugin n est PAS disponible dans une organization non autorisee
⨯ une organization non autorisee ne voit aucun plugin
⨯ activer dans une organization non autorisee est refuse par le service
⨯ un post forge sur une organization non autorisee est refuse
⨯ configurer une organization non autorisee est refuse
⨯ retirer l autorisation organization eteint la boucle sans reecrire sa ligne
Tests: 6 failed, 21 passed

Sabotage 2loop_plugins.configure retiré du socle facilitator :

⨯ owner et facilitator peuvent configurer le membre non
⨯ le facilitator active le plugin depuis la surface organization
⨯ le nouveau droit n elargit pas les droits cards
Tests: 3 failed, 24 passed

Arbre commité avant chaque salve, git diff vide après restauration.

Voisins — 238 verts (2443 assertions), grepés sur les contrats touchés :
T1079 Matrix + Resolver, T1090, T1118, T1123, T1124, T1125, T1127,
T1313 FacilitatorAuthority, T1331, UserDataLifecycleRegistry, T1614.

Recette navigateur — jouée sur https://test.laravel

Surface Constat
/admin/loops/{loop}/configure plugin à côté de « Résumé IA », badge EXPÉRIMENTAL, Activer → bandeau + état Activé + trace « Modifié le 21/09/2026 16:22 par Admin »
/org/main/loops/{loop}/outils zone « ACTIONS DE CHATLOOP » créée ; ne compte pas parmi les 3 mis en avant (Roadmap, Sondages, Événements)
écran de configuration Aperio / Traverse / Limen ; posture d'Aperio réécrite, enregistrée, relue — avec le défaut hérité rappelé dessous ; 1 seule ligne en base
Organization non autorisée « Actions de ChatLoop » ne contient que « Résumé IA » — plugin absent ; URL directe → 403 à un SuperAdmin
Console 0 erreur

Non vérifié — responsive : même limite qu'à TASK-1614, le viewport rendu ne
suit pas le redimensionnement de la fenêtre pilotée.


UX_DEBT_SLICE_E

Le facilitator détient loop_plugins.configure — service, routes et tests
le lui reconnaissent, et le sabotage 2 le prouve. Ce qu'il n'a pas, c'est le
chemin : /outils est gardé par canConfigure() des Cards, antérieur à
cette TASK.

Arbitrage : ne pas ouvrir cette page, ne pas toucher à canConfigure(), ne pas
élargir les droits Cards. Ouvrir /outils au facilitator lui montrerait la
grille de composition et ses boutons, que le serveur refuserait ensuite un par
un — exactement le défaut que TASK-1083 a corrigé.

La découvrabilité passe en SLICE E, sur une surface réellement accessible
depuis ChatLoop. Consigné comme dette, pas comme bug de TASK-1616.

Hors scope préservé

Ni CapabilityRegistry, ni AiEconomicGuard, ni ai_pricing, ni OpenRouter,
ni ProviderResolver, ni AiTurnLock, ni PromptRepository, ni Evidence
Build, ni follow-up, ni bouton « Demander aux 3 », ni génération. Le mot
« provider » n'apparaît que dans un commentaire qui dit que l'écran n'en
choisit pas.

Aucune logique Community. LoopPresetConfigurator et la doctrine Cards
intacts.

VERSION 1.616.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3

Cyril and others added 2 commits September 21, 2026 17:14
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqwjarKwhSbpzdPxLAmNh3
…tants se reglent (TASK-1616)

SLICE B de la Product Spec V0 « ChatLoop — 3 assistants IA ». Les deux
maillons suivants de la chaine posee par SLICE A :

    catalogue plateforme -> disponibilite Organization
      -> ACTIVATION BOUCLE -> CONFIGURATION DES 3 ASSISTANTS

LE PLUGIN N'EST PAS UNE LOOPCARD, et c'est la decision centrale.

Le bloc « Actions de ChatLoop » est pilote par les Cards de placement
chat_action (« Resume IA »). Modeliser le plugin ainsi aurait semble naturel
et aurait ete faux : LoopPresetConfigurator::canConfigure() est
proprietaire-only — « un animateur anime, il ne recompose pas » — et la
matrice mesuree donne loops.manage_cards = NON pour owner, facilitator ET
member, TASK-1083 l'ayant retiree au motif qu'elle annoncait un droit que
l'interface ne donnait pas.

Passer par la Card imposait donc de choisir entre exclure le facilitator
(contre le CDC §5) et percer une doctrine posee expres. Le plugin garde son
PROPRE etat, rendu A COTE de « Resume IA », et son PROPRE droit :
loop_plugins.configure — owner + facilitator, membre refuse, SuperAdmin et
Admin d'Organization par les etapes 3 et 4 du resolveur.

LE HARD GATE VIT DANS LE SERVICE, pas dans l'ecran. Cacher un bouton n'a
jamais empeche un POST : chaque lecture et chaque ecriture reconfronte la
disponibilite de l'Organization de la BOUCLE. Retirer l'autorisation eteint
toutes ses Boucles sans reecrire une ligne.

ECART, PAS COPIE. Une posture identique au defaut n'est pas stockee, et vider
un champ SUPPRIME l'ecart — sinon la Boucle figerait le texte du jour. Les
postures SURVIVENT a l'extinction, dans la Boucle comme dans l'Organization.

ZERO APPEL PROVIDER : ni capability, ni AiEconomicGuard, ni ai_pricing, ni
OpenRouter, ni AiTurnLock, ni Evidence Build, ni follow-up.

MESURES
  27/27 verts. Sabotage 1 (gate Organization neutralise) -> 6 rouges ;
  sabotage 2 (droit retire au facilitator) -> 3 rouges. Voisins : 238 verts.
  Recette navigateur : les deux surfaces, l'ecran des trois postures, la
  persistance relue, et 403 en URL directe sur une Organization non autorisee.

UX_DEBT_SLICE_E : le facilitator detient le droit mais n'atteint pas /outils,
garde par canConfigure() des Cards, anterieur a cette TASK. Arbitrage de
Cyril : ne pas ouvrir cette page, reporter la decouvrabilite a la SLICE E sur
une surface accessible depuis ChatLoop. Consigne comme dette, pas comme bug.

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 21, 2026
@cslucki
cslucki merged commit 998531f into develop Sep 21, 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