Communitygithub.com

De l'usage à l'expérience

Transformez un rapport d'usage (bug, friction, « pourquoi ceci est là ? ») en l'expérience que le produit devrait établir, trouvez la cause structurelle, corrigez-la, testez-la dans un vrai navigateur avec l'espace de noms navigateur de Beam Lisp, et conservez-la comme un scénario filmé avec les passages du modèle enregistrés.

Qu'est-ce que De l'usage à l'expérience ?

Cette compétence guide un agent IA pour transformer des rapports d'utilisation (bugs, frictions) en une expérience produit améliorée, en suivant un cycle structuré : collecte des traces d'usage, rédaction de l'expérience désirée, identification de la cause structurelle, test manuel dans un navigateur réel avec Beam Lisp, et enregistrement comme scénario filmé. Elle supporte le développement de produits collaboratifs comme Knowledger et s'appuie sur l'espace de noms navigateur de Beam Lisp (Chromium headless) pour les tests et les scénarios automatisés. L'agent apprend à écrire des phrases d'expérience (ex. « chaque point mène à sa place »), à utiliser des sondes de test (probes) avec des vérifications JavaScript, et à créer des films reproductibles à partir de cassettes (enregistrements des appels d'outils du modèle). L'accent est mis sur la reproductibilité, l'isolation des tests (copies reflink), et la documentation par la narration des films, avec une distinction claire entre le correctif et l'expérience rapportée.

Compatible avec~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/undefine-org/enchanted-skills/tree/main/ux-from-use

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait De l'usage à l'expérience ?

Un rapport nomme un symptôme. Le travail est l'expérience derrière. « Le client disparaît quand la conversation passe au sujet » est un bug. « Une conversation rassemble ce dont elle parle : le client reste quand son sujet est ajouté » est ce qu'il faut construire, vérifier et filmer. Écrivez d'abord cette phrase. Corrigez la structure qui a permis le symptôme, puis prouvez la phrase en utilisant le produit.

La boucle

  1. Collectez l'usage. Lisez le rapport, puis les traces d'utilisation réelle : les conversations, journaux, logs, présence, les fichiers touchés de la personne. Elles contiennent des attentes que personne n'a écrites (« ils en sont où ? » attend les points eux-mêmes, pas un résumé).
  2. Écrivez l'expérience. Une phrase par rapport, au présent, du point de vue de la personne, sans mots d'implémentation. Tenez la liste. Elle deviendra la narration du film et les messages des revendications.
  3. Trouvez la raison structurelle. Demandez pourquoi le produit a pu faire cela. Une cause explique généralement plusieurs rapports (identité tirée d'un nom d'affichage ; deux comptes qui partagent un mot ; un moteur de rendu qui supprime une classe lors de l'insertion). Corrigez la cause, pas l'écran qui l'a montrée.
  4. Utilisez-le vous-même. Pilotez la vraie application en tant que chaque personne impliquée, en largeur bureau et téléphone, via l'espace de noms navigateur (ci-dessous). Regardez les captures d'écran. Comptez ce que la page dit, pas ce que le code a l'intention de faire.
  5. Conservez-le. Transformez les étapes manuelles en scénario : les actions deviennent des événements, les vérifications deviennent des revendications, la phrase d'expérience devient la narration de la scène. Mettez les passages du modèle sur bande pour que le film se rejoue en secondes, sans coût.
  6. Rapportez l'expérience, pas le correctif. Dans le résumé, commencez par ce que la personne va maintenant trouver, puis la cause, puis le film et comment le rejouer.

Goût maison (ce qu'Othman a demandé, à plusieurs reprises)

  • Moins de copie. L'état est dessiné : ton, poids, emplacement, un anneau, une marque. Une phrase qui explique un écran signifie que l'écran est faux.
  • Un mot par idée. Tenez un glossaire et respectez-le : un « critère » (jugé par rapport à la procédure) n'est jamais un « point » (ce qu'une personne décide). Si deux comptes partagent un mot, quelqu'un les additionnera.
  • Les choses s'accumulent. Les étiquettes s'ajoutent (nature, puis client, puis sujet). La courante est remplie et les autres restent en contour. Ne remplacez jamais le contexte que la personne a déjà vu.
  • Les nombres dessinés avant le texte. Un historique s'ouvre sur des graphiques, une série chacun, valeurs étiquetées. Le texte se trouve en dessous, une ligne par événement, et s'ouvre à la demande.
  • Chaque référence mène à sa place. Un numéro de paragraphe fait défiler jusqu'au paragraphe et l'illumine. Une citation trouve son passage. La barre de défilement marque où se trouvent les choses, dans leurs couleurs.
  • En direct par défaut. Pas de rechargement complet. Un changement fait par une personne s'affiche sur chaque page ouverte en même temps. Des tapements répétés sur une page lente ne doivent pas répéter l'effet : les gestes sont idempotents.
  • Contrôles là où est la chose, et seulement pour ceux qui peuvent les utiliser. Les personnes en lecture seule voient l'état sans le contrôle.
  • Sachez qui est là. L'identité et le rôle atteignent chaque écran et chaque agent. Ne dites pas à un associé qu'« un associé doit confirmer ».
  • Bords honnêtes. Dites clairement ce que le produit ne fait pas encore. Ne pointez jamais un écran qui ne peut pas le faire.
  • La largeur téléphone est un lecteur de première classe : 16px de gouttières, pas de défilement horizontal (minmax(0,1fr), pas 1fr), et le compte toujours accessible.
  • Maquettes et narration dans la langue du produit (français pour Knowledger).

Test manuel avec l'espace de noms navigateur

Le navigateur natif de Beam Lisp (optional/browser-port dans l'arbre beam-lisp) exécute Chromium en mode headless dans un Sway privé sans affichage, avec une entrée de confiance et un screencast continu. C'est le même objet qu'un scénario pilote, donc une session manuelle se transforme en test sans être réécrite. Utilisez agent-browser pour un coup d'œil rapide. Utilisez l'espace de noms navigateur pour tout ce qui mérite d'être conservé.

Une fois par machine

cd ~/projects/beam-lisp/optional/browser-port
nix develop --command cargo build --release --locked --features native-browser
nix build .#runtime-wayland --out-link ~/.local/share/bl-browser/runtime-wayland   # chromium, sway, wayvnc
command -v ffmpeg || nix profile add nixpkgs#ffmpeg

Exécutez tout ce qui l'utilise avec bl run -p ~/projects/beam-lisp/optional/browser-port/bl … (ou bl test -p …).

Une sonde : un fichier, une personne, une entrée réelle

templates/probe.bl est le point de départ. Son noyau :

(ns probe (:require [browser.page :as page]))
(def rt (str (System/get_env "HOME") "/.local/share/bl-browser/runtime-wayland/bin/"))
(def p (page/open! {:executable (str (System/get_env "HOME") "/projects/beam-lisp/optional/browser-port/target/release/bl-browser-port")
                    :width 1440 :height 860
                    :launch {"profile" "/tmp/probe/profile" "runtime" "/tmp/probe/runtime"
                             "chromium" (str rt "chromium") "compositor" (str rt "sway") "vnc" (str rt "wayvnc")
                             "width" 1440 "height" 960}}))
(try
  ;; qui regarde : l'identité que le proxy ajouterait (ici les en-têtes Tailscale) ; elle atteint aussi la socket live
  (page/cdp! p "Network.enable" {})
  (page/cdp! p "Network.setExtraHTTPHeaders" {"headers" {"tailscale-user-login" "[email protected]" "tailscale-user-name" "timinou"}})
  (page/record! p "/tmp/probe/take.mp4" {:fps 24})          ; optionnel : toute la session en film
  (page/navigate! p "http://127.0.0.1:24025/a/sahel-…")
  (page/wait! p "document.documentElement.dataset.live==='1'") ; un prédicat JS, 30 s par défaut
  (page/click! p ".rv-rail a.para[data-goto]")               ; pointeur de confiance : bouge, presse, relâche
  (println (page/evaluate! p "scrollY"))                     ; demandez à la page ce qu'une personne verrait
  (page/screenshot! p "/tmp/probe/after.png")                ; puis REGARDEZ-la
  (page/stop-recording! p)
  (finally (page/close! p)))

Les verbes sont navigate! wait! click! hover! fill! key! drag! evaluate! screenshot! record! stop-recording! show-cursor! cdp!. cdp! atteint tout ce que Chromium offre d'autre : viewport, réseau, cookies, émulation (Emulation.setDeviceMetricsOverride pour un téléphone).

Habitudes qui rendent une sonde utile à conserver

  • Demandez à la page, pas au code. Chaque vérification est une expression JS qui retourne true quand une personne verrait la chose : nombre de lignes, texte d'une étiquette, scrollY, une classe sur l'élément sous le pointeur. Ces expressions deviendront les revendications sans changement.
  • Sélectionnez par sens. Donnez à l'application des attributs de données stables là où les tests en ont besoin (button.cell[data-person='Karim Saadi'][data-team='Associés']), jamais « le cinquième bouton ».
  • Soyez chaque personne. Ouvrez une page par personne avec son identité. Deux pages côte à côte prouvent le « live » : une agit, l'autre change sans rechargement.
  • Vérifiez le premier affichage et la page corrigée. Les applications live rendent le HTML une fois, puis corrigent à partir des données. Les bugs se cachent dans la différence (une classe supprimée lors de l'insertion, une liste commençant par du texte lu comme un nom de balise). Atteignez chaque écran une fois par URL et une fois en naviguant vers lui.
  • Attendez que la page soit live, pas seulement connectée. Un client live peut remplacer la page rendue par le serveur par le premier rendu de sa socket. Le texte tapé entre-temps est perdu, pour un test et pour une personne qui tape vite après le chargement. L'application doit conserver ce qui a été tapé pendant ce montage, puis dire qu'elle est live (data-mounted). Les tests attendent ce drapeau.
  • Regardez en largeur téléphone. Vérifiez document.documentElement.scrollWidth === innerWidth à 390px, puis regardez la capture d'écran.
  • Ne touchez jamais aux données réelles, et prouvez-le. Pointez l'application vers une copie reflink de ses données (cp -a --reflink=auto) et un port libre. Puis prouvez l'isolation avant de faire confiance : renommez une chose dans la copie (un canari : une équipe « AssociésX »), agissez dessus, et vérifiez que la copie a changé et que le timestamp du fichier réel n'a pas changé. Faites-le une fois par type de processus qui écrit (gestionnaires de page, sockets live, jobs en arrière-plan). Dans Beam Lisp, System/put_env depuis un test atteint les gestionnaires de page mais pas les sockets live : une socket qui ne lit aucun dossier de données configuré revient à la valeur par défaut, qui sont les données réelles. L'application doit épingler sa configuration à l'échelle de la VM quand son serveur démarre (persistent_term) et la lire à partir de là. Si vous devez toucher des données live, faites un instantané du fichier, agissez, différez pour confirmer seulement votre changement, restaurez.

De la sonde au film

Un scenario.demo/defdemo est un test ordinaire (bl test). Les étapes correspondent une à une :

SondeScénario
(page/navigate! p url)(s/does :othman [:navigate url])
(page/wait! p js)(s/does :othman [:wait js])
(page/click! p sel) / hover! / fill! / key![:click sel] [:hover sel] [:fill sel text] [:key "Enter"]
une pause pour l'œil[:pause ms]
(page/evaluate! p js) qui doit être vrai(s/sees :othman (fn [p _] (= true (page/evaluate! p js))) "l'expérience")
une personneun acteur dans browser.film/owned-worlds, enveloppé pour définir son identité à l'ouverture
un paragraphe de narration(demo/scene :id {:title … :say … :capture :video} events…)

templates/feature-demo.bl est un fichier complet : une copie isolée des données de l'application, l'application démarrée dans la VM de test sur un port libre, des mondes enregistrés avec identités, des pistes silencieuses quand aucune clé vocale n'existe, et une démo avec trois scènes. Exemple fonctionnel : knowledger-interface-review/apps/practice/test/features-demo.bl (cinq films : revue, historique, pièces, une équipe changée en direct entre deux personnes, une conversation sur bande).

Écrivez les scènes comme l'expérience, pas le correctif : « Chaque point mène à sa place », jamais « corrigez le gestionnaire §-link ». La narration est la documentation.

Passages du modèle sur bande

Tout ce qu'un agent fait doit passer par la porte d'outils de l'application elle-même, de sorte que seuls les choix du modèle sont ceux du modèle. Une bande conserve, pour une exécution du modèle, les appels de porte qu'il a faits dans l'ordre et sa réponse finale, indexés par un hachage du modèle, du prompt système et du prompt (avec les horloges, les nombres de type époque et les hex id masqués).

  • record : rejouez ce qui est sur bande, exécutez le modèle pour ce qui ne l'est pas, conservez-le.
  • replay (le défaut) : une exécution non sur bande est un tour d'erreur. Un rejeu ne revient jamais au modèle en silence.
  • Le rejeu fait les mêmes appels via la même porte, à un rythme donné, de sorte que le produit refait le travail et que l'écran le montre, en secondes et gratuitement.

Épinglez tout ce qui atteint le prompt (le nom du cabinet, la date s'il y en a une) dans les données de test, sinon la clé dérivera. Validez les bandes. Implémentation de référence : apps/practice/src/practice/cassette.bl et ses deux crochets dans conversation.bl (le tour et la porte).

Exécution et rendu

bl test -p ~/projects/beam-lisp/optional/browser-port/bl app/test/features-demo.bl             # rejouer, prouver, capturer
DEMO_RECORD=1 bl test -p …                       # mettre les passages manquants du modèle sur bande (nécessite les identifiants du modèle)
BL_DEMO_EXPORT=1 bl test -p …                    # également rendre MP4 + sous-titres + chapitres par film

Chaque film efface sa dernière prise dans son fixture, car un enregistrement n'en écrase jamais un. Gardez chaque narration dans les limites de deux lignes de sous-titres (environ 130 caractères), sinon le rendu la refuse. Une machine chargée peut affamer l'encodeur de screencast : vérifiez frames/recordings.json, où encodedFrames devrait être environ égal à secondes × fps, et relancez lorsqu'une prise est courte.

Le rendu (scenario.film/export!) nécessite Python 3 et FFmpeg avec libass. La narration est parlée quand DEEPGRAM_API_KEY est définie. Sinon chaque scène reçoit une piste silencieuse aussi longue que ses sous-titres prennent à lire. Ne supposez jamais qu'une clé vocale existe. Parcourez les films avec (scenario.demo/serve! dir {:port 4163}) sur loopback, ou publiez-le avec work serve.

Avant de dire que c'est fini

  • Chaque élément rapporté a sa phrase d'expérience, sa cause et une revendication qui la prouve dans un vrai navigateur, pour chaque personne concernée.
  • Largeur bureau et téléphone vérifiées, en captures d'écran, pas seulement asserté.
  • Premier affichage et page corrigée tous deux vérifiés pour chaque écran touché.
  • Comportement live prouvé avec deux personnes, là où c'est pertinent.
  • Aucune donnée réelle modifiée par le test. Tout ce qui a été touché est restauré, avec le diff montré.
  • Les films se rejouent depuis la bande sans réseau. Les bandes et les scénarios sont validés, les rendus ne le sont pas.
  • Le résumé commence par ce que la personne trouvera maintenant.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés