Aller au contenu

NotreCouple 1.2 — livre d’aventures et accomplissements

Cadrage mis à jour le 5 octobre 2026 : ancien périmètre V1.3 repris dans la prochaine release 1.2. Module Plane : notrecouple-release-12. Plan de livraison.

Le modèle, le moteur et le livre sont déjà intégrés à la 1.1.1 (PR #431, #646, #652 et promotion #953). Ce contrat décrit les invariants du socle et les extensions à terminer en 1.2 : récompenses/personnalisation, quête facultative et validation intégrée. Les anciennes références de lots sont conservées ; les preuves restantes se qualifient sans réimplémenter le socle.

Intention et boucle produit

Le couple construit un livre d’aventures commun en choisissant une activité, en participant chacun, en découvrant le résultat ensemble puis en conservant un jalon. La récompense rend visible ce vécu. La prochaine proposition donne envie de revenir à son rythme.

Trois horizons : progression dans Jouer pendant la séance, quête facultative sur une semaine, accomplissements permanents dans Nous. Une seule prochaine action dominante. La fin de séance reste une fin satisfaisante et propose aussi de terminer pour aujourd’hui.

La 1.2 comprend un livre dans Nous, douze accomplissements, trois familles, un prochain jalon, des récompenses visuelles et une quête hebdomadaire facultative. Aucun XP individuel, classement, score de qualité relationnelle, monnaie, boutique ou perte d’acquis pour absence. Les contenus de base restent accessibles. Aucun univers intime n’est obligatoire pour compléter une collection.

Lot 1 — contrat de comptage

L’unité 1.2 est une découverte partagée, et non une expérience réelle prétendument vérifiée. Le code actuel couple_play_store.daily_state expose revealed quand les réponses correspondent aux deux membres actifs. submit_answer écrit sous transaction et verrouille la sélection. Le moteur du lot 2 devra enregistrer la transition vers cet état au moment de la seconde réponse, dans la même transaction. Un GET, le polling ou une animation ne produisent aucun événement.

Événement projeté : shared_discovery_v1, clé unique (couple_id, day_key, activity_id), avec horodatage serveur de première révélation et identifiant d’univers issu du catalogue serveur. Rejouer la même activité le même jour ne compte qu’une fois ; un autre jour peut compter comme nouvelle découverte. Le client ne choisit ni couple, ni date de gain, ni univers autoritaire.

Un jour actif est une date UTC contenant au moins une découverte partagée, calculée depuis l’horodatage serveur du gain (pas depuis le day_key fourni pour la séance). Une semaine active est une semaine ISO UTC contenant un tel jour. Les deux réponses peuvent être asynchrones ; le gain est daté de la seconde. Le fuseau UTC est fixe pour cette version et doit être expliqué dans l’aide ; un changement de fuseau futur exige un contrat de migration.

Un univers exploré contient au moins une découverte partagée éligible. Le mapping activité→univers est versionné côté serveur ; un identifiant inconnu est exclu du compteur d’univers et doit être corrigé avant activation du catalogue. Le compteur de découvertes reste valable. Aucune pondération selon le caractère intime d’un univers.

Les marques learning_match et declic_match ne sont pas des prérequis : elles peuvent exister indépendamment d’une révélation dans le store actuel. Un souhait accepté, une invitation, une ouverture de page ou un accord à une proposition ne donne aucun point. Une expérience hors application pourra être ajoutée plus tard avec un contrat déclaratif explicite.

Catalogue initial : douze accomplissements

Les seuils sont des choix produit initiaux à évaluer en bêta. Les clés sont stables ; noms et illustrations pourront être révisés sans redonner les gains.

Clé Famille Nom Condition cumulée Récompense
experience_01 Expérience commune Le premier chapitre 1 découverte partagée Page d’ouverture
experience_05 Expérience commune Nos premières pages 5 découvertes Vignette duo
experience_15 Expérience commune Une histoire qui grandit 15 découvertes Cadre de chapitre
experience_30 Expérience commune Trente moments à nous 30 découvertes Couverture alternative
exploration_01 Exploration Une porte s’ouvre 1 univers Emblème d’exploration
exploration_02 Exploration Un autre regard 2 univers Vignette de voyage
exploration_03 Exploration Explorateurs 3 univers Cadre d’exploration
exploration_04 Exploration À la croisée des chemins 4 univers librement choisis Couverture exploration
regularity_days_03 Régularité On se retrouve 3 jours actifs Marque-page
regularity_days_07 Régularité Sept rendez-vous 7 jours actifs Marque-page illustré
regularity_weeks_04 Régularité Notre rythme 4 semaines actives Cadre de saison
regularity_weeks_12 Régularité Au fil du temps 12 semaines actives Couverture au fil du temps

Descriptions affichées : « Vous avez partagé N découvertes », « Vous avez découvert N univers ensemble », « Vous avez joué ensemble sur N jours / semaines ». Les jours et semaines ne sont jamais obligatoirement consécutifs.

Modèle durable et intégrité

Catalogue versionné : clé, famille, métrique, seuil, nom, description, reward_key, ordre. Gain : couple_id, achievement_key, catalog_version, unlocked_at, reward_key ; unicité couple+clé. Projection : événements minimaux, jours actifs distincts, semaines actives distinctes, univers distincts et agrégats. Les récompenses sont acquises sans consommation et leur équipement est facultatif, sans effet sur les compteurs.

La transaction du gain doit sérialiser la projection par couple, y compris si deux activités différentes franchissent simultanément un seuil. INSERT ON CONFLICT seul sur les événements ne suffit pas pour éviter un jalon manqué. Un rollback métier ne laisse aucun événement, compteur ni notification. Une reprise après erreur rejoue sans duplication. Les comptes de deux couples ne se croisent jamais, même avec le même activity_id et day_key.

Pas de backfill automatique au lancement : seuls les événements après activation produisent des gains. L’interface indique « Votre livre commence ici ». L’historique actuel ne permet pas de promettre une reconstruction complète des anciennes révélations, des appartenances et des dates. Aucun badge ancien n’est inventé.

Un changement de seuil ne retire pas les gains existants et ne réutilise pas une clé pour une autre signification. Les acquis ne diminuent pas avec l’inactivité. Les suppressions de données restent prioritaires : les gains et agrégats suivent le cycle de vie du couple, sans transfert vers un nouveau couple. Le départ d’un membre n’autorise plus de nouveaux gains en duo ; les droits du membre restant suivent le contrat d’effacement existant. Après effacement du dernier membre, événements, agrégats, gains, préférences visuelles et notifications associées sont purgés. Le lot moteur doit prouver la compatibilité restauration/anti-résurrection.

Ne conserver dans la projection aucun texte de réponse, prénom, e-mail, opinion ou contenu intime. Les identifiants et agrégats restent des données tenantisées. Les clés de déduplication sont conservées tant que leur source reste rejouable ; leur purge doit être coordonnée avec celle de la source, jamais indépendante. La matrice de conservation du lot data-lifecycle doit définir et valider ce cycle avant activation, sans durée arbitraire inventée ici.

Livre, prochain jalon et célébration

Dans Nous : couverture, pages de jalons par date, collection des trois familles et un prochain jalon. Les pages ne recopient pas les réponses. Les illustrations sont des assets éditoriaux partagés. Ajouter un souvenir personnel reste hors première livraison et exige un contrat séparé.

Le prochain jalon est le gain non acquis au ratio compteur/seuil le plus élevé, avec départage stable par ordre du catalogue. Un accomplissement terminé est retiré des candidats. Tous acquis : présenter le livre et proposer une activité libre, sans nouvelle exigence artificielle.

Lors d’un premier déblocage, afficher une célébration groupée courte et non bloquante, même si plusieurs badges arrivent ensemble. Lecture accessible, reduced-motion, pas de déplacement de focus automatique, pas de saut de scroll. L’état de présentation est propre à chaque utilisateur, les gains sont communs : A ne consomme pas la célébration de B. Un retry ne renvoie pas une succession de popups. Aucun e-mail d’accomplissement pour cette version ; la consultation dans l’application suffit.

Quête hebdomadaire facultative

Lot distinct. Le couple choisit une quête commune parmi des propositions éditoriales simples : deux découvertes dans la semaine, ou un univers encore non exploré. La semaine court du lundi 00:00 UTC au lundi suivant. Le choix crée une instance partagée unique ; deux choix concurrents doivent retourner le choix enregistré et permettre une modification explicite avant le premier progrès.

Seules les découvertes postérieures au choix comptent. Les deux participants n’ont pas à être présents simultanément. Une quête terminée attribue une vignette, une seule fois. À la fin de la semaine, une quête inachevée se ferme silencieusement sans dette, badge retiré ni message d’échec. Les récompenses éditoriales reviennent dans les rotations suivantes, sans rareté perdue à jamais. La progression permanente acquise pendant la quête reste conservée.

Découpage et critères de sortie

Lot Livrable Dépendances / sortie
achievements-model Présent contrat et catalogue Revue produit et vérification des sources métier ; aucune migration/runtime
achievements-engine Projection transactionnelle PostgreSQL et lecture tenantisée Modèle ; matrice data-lifecycle ; tests concurrence, reprise et effacement sur PostgreSQL réel
achievements-ui Livre, collections, prochain jalon et célébrations Moteur ; responsive, clavier, reduced-motion et stabilité polling
achievements-rewards Assets et personnalisation du livre Modèle puis moteur/UI ; choix partagé, droits de gain vérifiés serveur, alternatives accessibles
achievements-quests Quête hebdomadaire commune Moteur + récompenses ; concurrence de choix, frontière temporelle, expiration douce, retries
achievements-validation Recette intégrée 1.2 Tous les lots requis ; tests multi-couple, A/B, accessibilité, cycle de vie et mesure bêta sobre

Conserver les quatre clés existantes. Ajouter uniquement les deux Lots récompenses et quêtes, qui ont chacun leur comportement et leur recette. Aucune micro-story pour chaque badge. Plane pilote directement ces lots via son API. Les clés et références NC existantes sont conservées ; aucune écriture dans la branche historique plane.

Scénarios d’acceptation à implémenter dans les lots suivants

  1. Première réponse : aucun gain ; seconde réponse : une découverte et premiers gains, une célébration groupée.
  2. Même requête rejouée, refresh et deux onglets : compteurs identiques, aucune nouvelle récompense.
  3. Deux activités terminées simultanément au seuil : les deux découvertes comptent et le badge est gagné une fois.
  4. Réponse de B une autre semaine : gain daté de B côté serveur ; aucune semaine rétroactivement inventée.
  5. Trois mois d’absence : livre et badges intacts ; proposition de reprise sans reproche.
  6. Quatre univers non intimes explorés : collection exploration complète sans obligation d’un univers particulier.
  7. Suppression puis restauration : aucune donnée effacée ne revient via la projection.
  8. Deux couples avec mêmes activités : aucune lecture, notification ou récompense croisée.
  9. Animation réduite et lecteur d’écran : le gain reste lisible ; A et B peuvent chacun le découvrir.
  10. Dernière seconde d’une quête / retry après échéance : horodatage transactionnel décide, récompense unique.

Mesure bêta proposée : activation duo, retour J+7, semaines avec une découverte partagée, taux de réalisation volontaire des quêtes et retour qualitatif sur le plaisir/pression. Aucune collecte des réponses et aucun objectif de temps d’écran. Instrumentation à cadrer avec le lot bêta, sans tracker tiers ajouté par cette spécification.

Preuves et limites

Le contrat initial est livré par PR #431 ; moteur et livre sont intégrés via #646/#652, avec chargement corrigé par #951 et promotion 1.1.1 par #953. Les assets personnalisables, préférences et quêtes restent dans NC-18/19. NC-17 porte la recette intégrée 1.2 et la qualification des environnements effectivement exécutés. Les dix scénarios ci-dessus restent les critères de comportement ; leur présence dans une spécification ne constitue pas une preuve de recette.