quest'n'click 4.5.0 · r1

Construite pour quest'n'click 4.5.0, révision r1. Si elle est publiée, et laquelle est la courante, est dit par publication.json.

Passes de terrain : ce que seuls des gens et de vrais appareils vérifient

English · Type : procédure · Public : contributeur · Contexte : dépôt du moteur · Statut : prête · S'applique depuis : 4.1.20

Vue d'ensemble

La machine vérifie une release à chaque push : le solveur, les navigateurs en CI, l'archive, les budgets. Certaines vérifications demandent une personne ou un vrai appareil : un lecteur d'écran, Safari hors ligne sur un iPhone, des testeurs qui ne connaissent pas les énigmes, un Studio déployé. Ce sont les passes de terrain. Elles sont rapportées dans les notes de chaque release, sans bloquer (D12) : une release dit combien ont été faites. Cette page dit comment faire une passe, quoi rapporter, et comment une passe est vérifiée puis reportée sur un nouveau candidat.

Ce que vous obtenez

Un rapport JSON par passe, lié au candidate run essayé, vérifié par field:check, et la fiche de la release docs/dev/passes/<version>.md générée depuis ces rapports par field:report. Chaque passe est aussi une issue GitHub ouverte avec le label field-pass, que le mainteneur ferme une fois le test fait et son rapport vérifié.

Contexte et versions

Dans le dépôt du moteur, pour le mainteneur et les personnes qui testent une release. Le Field Kit (des rapports en JSON) existe depuis la 4.1.18, les bundles signés depuis la 4.1.19, le report d'une passe depuis la 4.1.20 ; la liste des passes s'allonge avec les versions (plus bas). Ce que dit cette page vaut à partir de la 4.1.20.

Prérequis

Où lancer les commandes

Dans le dépôt du moteur, sur votre machine. Les rapports s'écrivent sous .cache/field/<version>/ (non commité) ; la fiche va dans docs/dev/passes/<version>.md (commitée).

Étapes

  1. Écrire les rapports à not-run, liés au candidat que le tag nommera :

    # dans le dépôt du moteur
    npm run field:init -- --release=4.4.0 --candidate=<run id>
    

    La commande écrit un rapport par passe demandée à cette release, dans .cache/field/4.4.0, lié au commit du candidat, à l'id de son run et au SHA-256 de chaque fichier jugé, et télécharge à côté le candidate-manifest.json du run (et son attestation) avec gh run download. Elle y garde aussi les surfaces et les fichiers du site du candidat. Un rapport existant est gardé sauf avec --force ; --manifest=<fichier> fournit le manifeste au lieu de le télécharger, --dir=<dossier> choisit un autre dossier.

  1. Faire la passe comme son issue le décrit (quoi essayer, avec quoi, quelles preuves rendre), puis remplir son rapport : l'opérateur, le début et la fin, sur quoi, le scénario, le statut, et les fichiers de preuve sous evidence/.
  1. Vérifier le dossier :

    # dans le dépôt du moteur
    npm run field:check -- --dir=.cache/field/4.4.0
    

    Schéma, candidat, SHA-256 de chaque preuve, recherche de fuites. --require=<passId,…> nomme des passes qui doivent être passed (une gate ; aucune passe humaine ne bloque un tag, D12).

  1. Écrire la fiche :

    # dans le dépôt du moteur
    npm run field:report -- --dir=.cache/field/4.4.0 --out=docs/dev/passes/4.4.0.md
    

    Le tableau va entre <!-- field:begin --> et <!-- field:end --> (ou à la place de la section « ## People's passes » de la fiche, ou dans une nouvelle fiche). Commiter la fiche. Elle est générée depuis les rapports, jamais retouchée à la main pour devenir un succès.

  1. Fermer l'issue. Le mainteneur ferme l'issue field-pass de la passe une fois le test fait et son rapport vérifié. Une issue ouverte est une passe non faite.

Les passes, par id

Une passe a un id stable (tools/field/schema.ts). Une passe ajoutée plus tard n'est pas demandée à une release plus ancienne (passesFor) : 13 de la 4.1.18 à la 4.2.0, 21 pour la 4.4.0, 22 à partir de la 4.5.0.

IdCe que c'estDemandée depuis
bridge-postgres-httpsUn Bridge multi-instance derrière HTTPS sur Postgres, un worker tué en pleine vérification4.1.18
runs-real-playersDes runs Histoire, Remix et Daily soumis par de vraies personnes4.1.18
run-resume-power-cycleUn run repris après l'arrêt et le redémarrage de la machine4.1.18
code-wheel-humanLa roue à code imprimée et utilisée à table ; l'alternative texte par une personne avec lecteur d'écran4.1.18
mystery-deployedUn monde Mystery joué depuis le menu Remix contre un Bridge déployé4.1.18
safari-ios-offline-updateSafari hors ligne sur un iPhone, et sa mise à jour4.1.18
firefox-real-offlineFirefox hors ligne sur une vraie machine4.1.18
phone-both-renderersUn vrai téléphone avec les deux peintres4.1.18
livesplit-obsUne vraie session LiveSplit et OBS4.1.18
connectors-real-securityDe vrais connecteurs et la passe de sécurité d'une personne4.1.18
blind-playtestersDes testeurs qui ne connaissent pas les énigmes4.1.18
voices-listeningLes voix écoutées4.1.18
archive-human-installL'archive publiée installée par une personne4.1.18
studio-hostedLe Studio Server déployé sur Clever Cloud (Node, PostgreSQL, Cellar, Keycloak, un domaine TLS), depuis son archive, en suivant son guide ; un vrai Safari sur macOS et iOS4.2.1
studio-collabTrois personnes sur un même Studio hébergé, une coupure réseau et un redéploiement pendant qu'elles éditent4.2.1
studio-previewSur un Studio hébergé, des personnes jouent la révision partagée sans serveur de dev, une sauvegarde qui passe d'une révision à l'autre, la pastille de santé, leur propre annulation, un build publié4.2.2
studio-assets-hostedLa préparation d'un Studio hébergé sur le worker (Python, ffmpeg), le jeu d'assets préparé joué dans l'onglet Play4.2.2
studio-mcp-remoteUn agent IA sur un Studio hébergé par son MCP distant (/mcp) : un vrai client MCP, le jeton d'un membre, une écriture au journal au nom du membre, un pan tenu par un autre refusé4.2.3
studio-oidc-genericLe Studio Server derrière un second fournisseur OpenID Connect (GitLab, D44) : connexion, rôles, un membre révoqué refusé, vérifié par une personne4.2.3
heroes-two-languagesL'exemple des héros (games/heroes) sur un vrai téléphone, en anglais et en français : la carte, le nom, les répliques et la voix de chaque héros, une sauvegarde reprise4.4.0
studio-hero-matrixLa matrice héros × langues du Studio lue par un auteur sur son propre jeu : ce qu'elle montre, ce qui manque, ce qu'elle devrait dire4.4.0
docs-beginner-readerUne personne débutante cherche dans la documentation publiée la réponse à dix vraies questions (BEGINNER-READER.md) : trouvée, absente ou mal comprise, dans sa langue4.5.0

Testeurs (blind-playtesters)

  1. Envoyer l'URL du jeu. Dire seulement : « joue comme tu veux ; quand tu t'arrêtes, fini ou pas, ouvre le menu pause et touche Partager la session ». N'expliquer aucune énigme, même sur demande : noter la question.
  2. Partager la session fait un fichier avec les entrées depuis le début de la partie (ids et indices seulement, pas de texte du journal, pas de nom), la famille d'appareil (ios, android ou desktop, rien de plus fin) et les tapes manquées (une tape sur rien à côté d'une cible, par lieu et cible). Le testeur l'envoie comme il veut.
  3. Déposer les fichiers dans games/<id>/playtests/ (commité ; npm run audit le couvre), puis, dans le dépôt du moteur :
    • npm run playtests -- --out=.cache/playtests : temps de jeu par lieu, où les joueurs bloquent, indices montrés, où ils se sont arrêtés, tapes manquées, une carte de chaleur sur le graphe d'énigmes ;
    • npm run verify:field : verify:commercial, puis cinq sessions qui se rejouent encore, trois jouées jusqu'au bout, deux familles d'appareils. Ces nombres sont les quotas d'une release testée par des joueurs ; un jeu peut en demander plus avec npm run playtests -- --strict --require=N --require-completed=N --require-devices=N.
  4. Ce que montre le rapport devient du travail : un blocage est une énigme à mieux indiquer, une tape manquée une zone à élargir, un abandon un endroit à regarder. Les sessions restent : quand le contenu change, elles peuvent ne plus se rejouer, et --strict dit lesquelles (les réenregistrer ou les supprimer).

Les playtests côté auteur : Playtests.

La fiche écrite à la main (avant la 4.1.18)

Avant le Field Kit, la fiche d'une release était une copie de docs/dev/passes/TEMPLATE.md remplie à la main avant le tag, « not done » laissé là où rien n'avait été fait, et scripts/release-notes.mjs mettait le tableau dans les notes de release avec « n of 7 done ». Le modèle garde ces sept vérifications, et les notes de release les nomment encore quand une release n'a pas de fiche du tout :

#PasseCommentÀ rapporter
1Lecteur d'écranSCREEN-READER.md : VoiceOver sur iOS ou TalkBack sur Android, une partie de l'écran titre à la première énigme résoluela ligne de la fiche : appareil, OS, ce qui n'a pas pu être atteint ou n'a pas été lu
2Safari hors ligneSAFARI-OFFLINE.md : première visite en ligne, mode avion, un lieu jamais visité, un rechargementla ligne : versions d'iOS et de Safari, l'étape qui a échoué
3Un vrai téléphonela scène la plus lourde (le marché de référence, le jardin de la démo) sur un téléphone milieu de gamme, avec le compteur (?fps)le FPS le plus bas vu (≥ 30 voulu), le téléphone
4Testeurscinq personnes qui ne connaissent pas les énigmes, chacune sur son téléphone, sans aideleurs fichiers de session (plus haut), puis npm run verify:field
5Voix enregistréesnpm run voices -- check --release après l'enregistrement : répliques validées sur répliques avec un idle compte, les répliques restantes
6Écoutechaque partition sur le haut-parleur d'un téléphone et au casque : les stems suivent le jeu, chaque pont une fois, rien de coupé, rien qui continue après le chargement d'une sauvegarde, une voix pendant un pontla ligne, et chaque défaut avec son lieu et ce qui a été entendu
7Tag signégit tag -s vX.Y.Z avec la clé du mainteneur, git tag -v le montrela ligne

Depuis la 4.1.18, le tableau « People's passes » de la fiche est écrit par field:report ; les notes de release ne comptent comme fait que passed (« n of N done »), et comme non fait not-run, blocked, failed (ou l'ancien « not done »).

Le Field Kit : ce que dit un rapport, et ce qui est refusé

Depuis la 4.1.18, une passe est un rapport JSON, plus une ligne éditée à la main : un fichier par passe, lié au candidate run qu'il a essayé (son commit, l'id de son run et le SHA-256 de chaque fichier jugé), dans un dossier qui garde aussi le candidate-manifest.json de ce run.

Limite · leak-scan-patterns La recherche de fuites est une barrière d'hygiène faite de motifs, pas une preuve. Le schéma refuse un champ qu'il ne nomme pas, et un rapport qui contient une clé, un jeton, une adresse email ou un bearer est refusé ; mais la recherche ne voit pas un secret pour lequel elle n'a pas de motif, et dans une image ou un binaire elle ne cherche que des clés et des jetons. Relisez ce que vous joignez.

Limite · integrity-not-authenticity field:check vérifie l'intégrité, pas l'authenticité : un rapport est vérifié contre le candidate-manifest.json posé à côté, tel quel. field:init le télécharge depuis le run lui-même, mais un dossier dont le manifeste a été modifié se vérifie contre cette modification. La gate de la release lit le manifeste du run, jamais celui du dossier.

Les bundles : ce que porte un ticket de reproduction

# dans le dépôt du moteur
npm run field:bundle -- --report=<report.json> --out=<bundle.tar.gz>
npm run field:verify-bundle -- <bundle.tar.gz>          # intégrité, puis authenticité sur GitHub
gh attestation trusted-root > trusted-root.jsonl        # une fois, en ligne
npm run field:verify-bundle -- <bundle.tar.gz> --offline --trusted-root=trusted-root.jsonl

Reporter une passe sur un nouveau candidat

Une passe est liée à sa surface : les fichiers du candidat qu'elle lit (docs/dev/surfaces.json, le qualification-surfaces.json attesté ; le site construit compte fichier par fichier), la configuration qu'elle lit dans le dépôt, et les passes dont elle dépend (ADR 0024). Quand rien de tout cela n'a changé entre le candidat essayé et un nouveau, version comprise, la passe peut valoir aussi pour le nouveau :

# dans le dépôt du moteur
npm run field:init -- --release=4.1.21 --candidate=<new run>   # garde aussi les surfaces et les fichiers du site du nouveau candidat
npm run field:carry -- --from=.cache/field/4.1.20 --to=.cache/field/4.1.21 --pass=safari-ios-offline-update

Résultat attendu, et comment le vérifier

field:check se termine sans erreur sur le dossier ; docs/dev/passes/<version>.md montre le tableau avec « x passed, y failed, z blocked, n not run, of N » ; les notes de release de cette version disent « n of N done ». Sur GitHub, les issues field-pass ouvertes sont les passes encore à faire : https://github.com/wanoo/quest-n-click/issues?q=label%3Afield-pass.

Erreurs fréquentes

SymptômeCauseCorrection
Le rapport du candidat précédent ne passe pasAutre commit, autre passe : ses empreintes ne sont pas celles du nouveau candidatRefaire la passe, ou la reporter (plus haut) si sa surface n'a pas changé
field:check refuse un rapport qui contient une adresse email ou un jetonLa recherche de fuitesLe retirer du rapport et de ses preuves
Une preuve refuséeUn lien, un fichier hors du dossier, une archive, ou plus de 16 MioMettre le fichier lui-même sous evidence/, décompressé
field:carry refuse et nomme un fichierUn fichier de la surface de la passe a changéFaire la passe sur le nouveau candidat
npm run verify:field échoue sur les quotasMoins de cinq sessions qui se rejouent, trois finies, deux familles d'appareilsPlus de testeurs, ou réenregistrer les sessions que le changement de contenu a cassées

Fichiers ou données modifiés

Revenir en arrière

Un rapport est un fichier : le modifier de nouveau et relancer field:check. field:init --force réécrit les rapports à not-run (il écrase ce que vous avez rempli). Un report déjà approuvé dans un commit signé se défait par un nouveau commit qui le retire ; un report avec un seul commit non signé sur son chemin reste refusé.

Références


Modifier la source de cette page · Signaler une erreur