# Cahier d'analyse — Atelier narratif de BIG EGG

29/09/2026 · Proposition acceptée par l'auteur, **étape 1 livrée** (voir
l'encadré ci-dessous).

> **Décisions de l'auteur (29/09/2026)**
>
> - **Le publié seulement.** Le brouillon vit trop peu pour valoir d'être
>   montré : l'atelier ne lit que `load_master`. Le sélecteur Publié /
>   Brouillon des §3, §9 et §11 est abandonné.
> - **Remplissage en sens unique.** Le tableau se remplit tout seul à partir
>   de ce qui est publié ; la quête de Bob y apparaît sans saisie.
>
> **Étape 1 livrée.** Elle se trouve à l'adresse
> `tools/game-data-manager/narrative/`, servie par le serveur du gestionnaire
> à `/narrative/`. Elle comprend :
>
> - le graphe calculé d'une quête ou d'un personnage, avec les trois sortes de
>   liens (plus « présence » pour les situations calculées) ;
> - l'inspecteur, qui donne phrases, emplacement exact et onglet du
>   gestionnaire ;
> - les avertissements prudents ;
> - la disposition des cartes mémorisée dans `data/narrative_plan.json`.
>
> Sur Bob, l'index rassemble seul 47 fiches : 9 moments, 12 scènes, 4
> répliques, 4 salles, l'employé, la créature et le compteur d'El Tuna.
>
> Tests : `tests/narrative_index_test.js`, `narrative_safety_test.js` et
> `narrative_plan_test.php`.
>
> **Refonte du 29/09 : une seule sorte de carte, le moment.** La première
> version montrait 14 sortes de cartes (quête, scène, état, salle…) : c'était
> illisible. Désormais, chaque carte est un moment, quelque chose qui arrive :
>
> - un déclencheur ;
> - une réplique (titrée par sa scène) ;
> - une salle qui peut apparaître, une vague, un PNJ qui s'en va ;
> - un client qui vient, un employé embauchable.
>
> Le détail n'apparaît qu'à la sélection, dans cet ordre : quand, où, qui, ce
> que voit le joueur, ce qui change, ce que ça rend possible, ce qui
> l'empêche. Sans sélection, le panneau montre la fiche de l'histoire :
> journal, personnages et leurs incarnations, lieux, récompenses, valeurs.
>
> Deux sortes de flèches seulement : « rend possible » et « se passe là /
> ensuite ». Un effet qui rend une condition fausse (le Lance-œufs interdit de
> revoir El Tuna) n'est pas une flèche, pour ne pas remonter le fil à
> l'envers : il est cité dans « Empêché par ». Bob tient en 27 moments.
>
> **Frise par étapes (29/09).** Les colonnes « qui écrit avant qui lit » ne
> faisaient pas une chronologie : deux moments simultanés se suivaient, et
> l'arc du duel, que rien ne relie à la quête dans les données, s'affichait en
> premier. Une quête est désormais rangée en bandes, selon son propre journal :
>
> 1. Avant la quête ;
> 2. une bande par étape ;
> 3. Quête réussie ;
> 4. Quête échouée ;
> 5. Hors de la trame.
>
> Chaque moment va dans l'étape qu'il exige (état, étape) ou, à défaut, dans
> celle du moment qui le rend possible. Le détail dit pourquoi.
>
> Le duel reste « hors de la trame » : il dépend du compteur « El Tuna tués »,
> tenu par le jeu. C'est à l'auteur de le placer, et les liens « suite
> proposée » de l'étape 2 serviront à cela. Les flèches « se passe là »
> n'apparaissent plus que pour le moment choisi.
>
> **Événements et ouvertures (29/09).** La frise mélangeait encore deux
> natures. Des *événements* : ce qui arrive (Bob entre au restaurant, Bob est
> servi). Des *ouvertures* : ce qui devient seulement possible (Bob peut venir,
> la Chevauchée se débloque, la planque peut apparaître). D'où deux cartes pour
> « l'arrivée de Bob », et un « Bob est servi » placé avant le déblocage de son
> plat.
>
> Désormais, une carte = un événement. Une ouverture s'affiche dans
> l'événement qui l'ouvre ou la ferme (« Bob entre au restaurant : ouvre la
> Chevauchée et la planque, ferme le retour de Bob »). Un événement hérite des
> conditions de ce dont il dépend :
>
> - le lieu où il se passe ;
> - le plat unique qu'un client mange (`fixed_recipe`).
>
> Deux actions du joueur deviennent des événements, déduits des données :
>
> - mettre le plat de côté à la console (`set_aside` de la quête) ;
> - vaincre une créature qui résiste aux autres armes. El Tuna ne prend que
>   5 % des coups directs, seul le Lance-œufs le touche : « El Tuna vaincu »
>   vient après « Bob donne le Lance-œufs » et ouvre le défi.
>
> Plus rien de Bob n'est « hors de la trame ». Enfin, seules les cartes
> déplacées à la main sont retenues dans le plan. Enregistrer toutes les
> positions figeait la mise en place d'une version précédente.
>
> **Cartes lisibles sans cliquer (29/09).** Retours de l'auteur :
>
> - c'était trop chargé ;
> - les zones de fond par étape n'apportaient rien ;
> - les cartes devaient dire l'essentiel directement.
>
> Désormais :
>
> - les zones de fond disparaissent. Les colonnes suivent toujours l'ordre de
>   la quête, et l'étape s'écrit en petit sur chaque carte ;
> - les cartes font 320 px et montrent : quand, où et qui, la première
>   réplique de la scène, ce qui change (récompenses en évidence), ce que ça
>   ouvre et ce que ça ferme ;
> - une condition que l'événement parent exige déjà n'est plus répétée chez
>   l'enfant. Elle reste consultable, repliée, dans le détail.
>
> **Flèches sans redondance (29/09).** Une flèche n'est gardée que si elle
> apporte une condition réellement montrée sur la carte d'arrivée. « El
> Tuna » ne pointe plus vers chaque événement de la planque : « Bob entre au
> restaurant » exige déjà la quête en cours. Bob passe de 40 à 25 flèches, et
> seul El Tuna, le vrai début, reste sans flèche entrante.
>
> Trois garde-fous :
>
> - un parent ne cache une condition que s'il vient plus tôt ;
> - il doit garder lui-même une flèche vers l'enfant, pour qu'une condition
>   repliée soit toujours portée par une flèche visible ;
> - il ne doit pas remettre lui-même cette condition à faux (fait réarmé).
>
> **Recentrage et étape 2 livrée (29/09).** L'auteur a relevé que l'outil ne
> permettait toujours pas d'écrire, alors que c'est son objectif premier :
> l'étape 1 (la lecture de Bob) avait absorbé cinq refontes au lieu d'être une
> courte preuve.
>
> Avant de passer à l'écriture, la lecture a reçu une dernière correction, le
> fil d'une salle :
>
> - on y entre, il s'y passe des choses, on la nettoie après ses vagues ;
> - une salle fermée ne se traverse pas : « Bob est servi » au restaurant ne
>   mène plus à « Bob, repu », qui se dit dans la planque.
>
> Puis l'étape 2 a été livrée : écrire.
>
> - **+ Intrigue** crée une histoire à soi.
> - **+ Idée** pose une carte (double-clic sur le fond : à cet endroit). Elle
>   contient un titre, ce qui se passe, et des listes : quand, où, qui, ce
>   qui change, récompense.
> - Chaque carte a un statut (Idée, À préciser, Prête à réaliser, Dans le jeu),
>   les marqueurs `!!` / `%%`, des notes et un « réalisée par » qui la
>   rattache à un vrai événement.
> - **+ Idée après** enchaîne une idée déjà reliée, aussi après un vrai
>   événement ; **Relier à…** tire un lien de cause à effet, avec une raison
>   facultative.
> - Un nom qui correspond à une vraie fiche est « dans le jeu », sinon « à
>   créer ». La fiche de l'intrigue réunit la liste **À créer dans le jeu**.
> - Annuler / refaire.
>
> Tout vit dans `narrative_plan.json`, validé côté serveur.
>
> Tests : `narrative_plan_model_test.js` et `narrative_browser_test.js`. Le
> second rejoue les gestes réels au navigateur, requêtes interceptées, aucun
> fichier réel touché.
>
> Reste à venir : l'export Markdown (la fiche d'implémentation, étape 3) et
> les motifs narratifs.
>
> **Écran tactile (29/09).** Gestes pris en charge :
>
> - un doigt glisse une carte ou le tableau, avec une tolérance plus large qu'à
>   la souris ;
> - toucher choisit ;
> - pincer zoome autour du point entre les doigts, et deux doigts font aussi
>   glisser ;
> - double-toucher le fond pose une idée ;
> - le pincement du pavé tactile zoome.
>
> Le tableau garde les gestes pour lui (`touch-action: none`), et les cibles
> grossissent sur écran tactile. Test : `narrative_touch_test.js`, qui envoie de
> vrais événements de doigts au navigateur.
>
> **Liens vers le gestionnaire, ordre automatique puis parlé (29/09).**
>
> Chaque vraie fiche a son ↗ : événement, personnage, salle, scène, ce qui
> s'ouvre, noms reconnus dans une idée. Charger le gestionnaire abandonne son
> brouillon non publié. Un onglet déjà ouvert reçoit donc la demande par
> message (`BroadcastChannel`) et va à la fiche sans se recharger ; sinon un
> onglet s'ouvre sur `#fiche=collection:id`. Côté `app.js`, c'est un ajout de
> 30 lignes, qui passe par `openRecord`.
>
> Nouvelle règle : ce qui part tout seul (un déclencheur) passe avant ce qu'il
> faut aller chercher (une réplique). Bob reçoit son plat → Bob donne le
> Lance-œufs → « Bob, repu », si on lui reparle.
>
> Correction : un pointeur perdu bloquait le tableau, puisqu'il faisait croire
> à un pincement. Un premier contact remet désormais les gestes à zéro.
>
> Deux tests suivent ces points : `narrative_manager_link_test.js` et
> `narrative_touch_test.js`.
>
> **« Fait parler » séparé de la boîte de dialogue (schéma 92, 29/09).**
> Jusqu'ici, `story_triggers.character` disait à la fois :
>
> - la boîte de dialogue d'une scène ;
> - sans scène, quel personnage ouvrir son dialogue. Ce second rôle était
>   invisible, et il fait marcher « Bob accueille dans sa planque ».
>
> Désormais, `dialogue` (« Fait parler ») porte ce rôle, et `character`
> (« Boîte de dialogue de ») n'est plus que l'apparence. Une scène et « Fait
> parler » s'excluent : choisir l'un vide l'autre dans l'éditeur, et la
> validation refuse les deux ensemble.
>
> `migrate_schema_92.php` reprend « Fait parler » pour les déclencheurs sans
> scène : seul `bob_hideout_greeting` était concerné, et le comportement en
> jeu est inchangé.
>
> Dans l'atelier, ce déclencheur relie ses répliques possibles (« Bob parle de
> lui-même, selon la situation »), sauf celles qui contredisent la salle. Autre
> correction : une réplique se dit partout où le personnage est incarné, au PNJ
> d'une salle et au client attablé. « Bob le cheval est servi » mène donc bien
> à « Bob, repu » (on lui parle pendant qu'il mange). La règle « salle
> fermée » ne s'applique qu'aux personnages présents dans une seule salle.
>
> Note : 14 tests du gestionnaire (arbre d'upgrades, meubles, recettes…)
> échouent aussi sans ce changement. Ils ont été relancés avec l'`app.js`
> précédent, et ils portent sur les données d'auteur en cours.
> L'inspecteur nomme donc l'onglet et copie l'identifiant, parce qu'ajouter
> un lien direct demanderait de toucher `app.js`.

Ce cahier fusionne deux analyses :

- [proposition-outil-narratif.md](proposition-outil-narratif.md), la première
  analyse ;
- [proposition-atelier-narratif.md](proposition-atelier-narratif.md), l'analyse
  tierce.

Il les réorganise autour des priorités que l'auteur a fixées ensuite. Les deux
documents restent des sources ; en cas de désaccord, c'est ce cahier qui fait
foi.

---

## 1. Les priorités de l'auteur, dans l'ordre

1. **Ne rien mettre en péril.** L'atelier ne remplace ni ne fragilise le
   gestionnaire de données, le moteur, le maître ou les sauvegardes.
2. **Enlever les freins à l'écriture.** Mettre une narrative élaborée « sur
   papier », vite, sans devoir penser en identifiants dès la première minute.
3. **Comprendre le terrain.** Voir ce que le jeu sait déjà faire, et comment
   l'existant s'articule.
4. **Créer les vrais éléments** : un plus, pas une condition. Il doit venir sans
   rogner sur la priorité 1.

Toute décision de ce cahier se juge dans cet ordre. Quand deux options
s'opposent, la plus sûre gagne.

---

## 2. Ce qui change par rapport aux deux analyses

| Sujet | 1re analyse | Analyse tierce | **Retenu ici** | Pourquoi |
|---|---|---|---|---|
| Emplacement | Onglet dans `app.js`, partageant ses données | Page dédiée du même outil PHP | **Page dédiée, dans son propre dossier** | `app.js` fait 11 500 lignes ; ne pas y toucher protège le système actuel (priorité 1). |
| Source des données | Le brouillon | Choix explicite Publié / Brouillon | **Choix explicite** | Les deux fichiers diffèrent réellement. |
| Liens calculés | « Écrit → lit » présenté comme une causalité | « Influence », pas de causalité promise | **« Influence »** | Écrire `false` ou ajouter 1 ne garantit pas qu'une condition devienne vraie. |
| Diagnostic « lu jamais écrit » | « Condition morte » | « Aucun producteur déclaré » | **« Aucun producteur déclaré »** | Le moteur peut écrire des valeurs sans déclaration (compteurs). |
| Étapes du journal | Non traité | Ne sont pas des transitions | **Affichées comme journal, jamais reliées entre elles** | Ce sont les scènes et effets qui écrivent `stage`. |
| Incarnations d'un acteur | Non traité | Une identité, plusieurs incarnations | **Retenu**, avec confirmation par l'auteur | Il existe même une copie `bob_the_horse_copy` : pas de fusion sur le nom. |
| Récompenses | Catalogue calculé | Intentions, et distinction disponible / offert / possédé / équipé | **Les deux, plus les conséquences négatives** | |
| Créer les vrais éléments | Boutons de création (C) | Écriture ciblée au brouillon, plus tard | **Fiche d'implémentation exportée d'abord** (§8) | Obtient l'essentiel du bénéfice sans aucune écriture. |
| Freins à l'écriture | Peu traités | Champs libres possibles | **Écriture à deux vitesses et motifs narratifs** (§4, §7) | C'est le cœur de la priorité 2. |

---

## 3. Garanties de sûreté (priorité 1)

Ces garanties forment le **contrat** de l'atelier. Chacune est vérifiable par
un test.

| L'atelier… | Règle | Vérification |
|---|---|---|
| lit le jeu | Uniquement par `GET api.php?action=load` (brouillon s'il existe, sinon maître) et `GET …load_master`. Ces deux lectures n'écrivent rien. | Test : le code de l'atelier ne contient aucun appel à `autosave`, `publish` ni `reset_draft`. |
| écrit | **Un seul fichier** : `tools/game-data-manager/data/narrative_plan.json` (nom proposé). Son propre petit point d'entrée PHP a un chemin figé : aucun paramètre ne peut viser un autre fichier. | Test : empreintes du maître, du brouillon et d'une sauvegarde joueur identiques avant et après une session d'atelier. |
| enregistre | Écriture dans un fichier temporaire puis renommage, copie de secours, contrôle de version (refus si le plan a changé ailleurs, comme l'autosauvegarde du gestionnaire). | Test d'aller-retour : enregistrer, recharger, exporter, importer. |
| touche au gestionnaire | Au plus **un lien** dans sa navigation, et même ce lien est facultatif (un favori suffit). | Diff Git d'`app.js` et `index.php` vide ou d'une ligne. |
| touche à Godot | **Jamais** : pas de schéma, d'autoload, de `Loc` ni de scène. | Aucun contrôle Godot à lancer. |
| se désinstalle | En supprimant son dossier. Le plan reste un simple JSON suivi par Git. | — |

**Risque résiduel connu** : Google Drive peut verrouiller un fichier au moment
du renommage (déjà vu sur le rapport du runner). L'enregistrement doit alors
échouer proprement, garder l'ancien plan et le signaler. Le travail d'un plan
n'est jamais un fichier du jeu, donc ce risque ne touche que l'atelier.

---

## 4. Les freins actuels à l'écriture (priorité 2)

Pourquoi écrire une quête est difficile aujourd'hui, même avec de bons
formulaires :

1. **Il faut penser comme le moteur dès le départ** : identifiants, adresses,
   facts, déclencheurs. L'idée doit être traduite avant même d'être écrite.
2. **L'histoire est éclatée.** Bob occupe environ 30 fiches, dont 9
   déclencheurs, une douzaine de scènes, 4 facts, 5 salles et 5 incarnations,
   réparties dans une douzaine d'onglets. Aucune vue ne les montre ensemble.
3. **Des règles invisibles** changent le sens de ce qu'on écrit :
   - la **première** réplique vraie gagne (ordre = priorité) ;
   - un déclencheur part quand ses conditions **deviennent** vraies, au bon
     lieu, et applique ses effets **avant** que sa scène soit visible ;
   - une liste de conditions se lit **toujours en ET** ;
   - les **étapes du journal** ne sont pas des transitions ;
   - les **portées** diffèrent : la quête de Bob est `meta`, son emploi
     `dimension` ;
   - une variante de salle est **admissible**, pas garantie : 50 % pour la
     planque au niveau 3, 25 % pour le défi au niveau 4 de la dimension 1.
4. **Nulle part où mettre ce qui n'existe pas encore** : un personnage à
   inventer, une salle à dessiner, une récompense à définir.
5. **Pas de catalogue des récompenses par intention**, et des mots proches
   faciles à confondre : disponible, offert, choisi, possédé, équipé.

### Réponse : l'écriture à deux vitesses

Chaque carte de l'atelier monte une **échelle de maturité**, sans jamais être
bloquée à un échelon :

| Échelon | Ce que l'auteur fait | Ce que l'atelier montre |
|---|---|---|
| **1. Idée** | Écrit en texte libre : « Bob a faim et demande un plat. » | Une carte en pointillés. |
| **2. Intention structurée** | Choisit acteurs, lieux, conditions et récompenses dans les catalogues, ou « + à créer ». | Ce qui est compatible avec le moteur, ce qui reste « à implémenter ». |
| **3. Reliée au jeu** | Rattache la carte aux vraies fiches qui la réalisent. | La carte devient pleine, avec lien vers chaque fiche source. |
| **4. Vérifiée en jeu** | Coche après avoir joué la séquence. | Jamais coché automatiquement. |

Tous les champs acceptent du texte libre. Structurer est une aide, jamais une
obligation. Les marqueurs de Taskmaster restent : `!!` pour « à continuer »,
`%%` pour « à déterminer ».

---

## 5. Comprendre le terrain (priorité 3)

### 5.1 Où vivent les conditions

**Chacune vit sur le mécanisme qu'elle contrôle.** L'atelier les rassemble
autour d'une carte en affichant leur emplacement réel ; il n'en crée aucune
nouvelle.

| Question d'auteur | Emplacement réel | Exemple Bob |
|---|---|---|
| La salle peut-elle apparaître ? Où, avec quelle chance ? | `rooms.x.conditions` + `replaces` | Planque : quête en cours, étape ≥ 1, niveau 3 de la dimension 1 à 50 %. |
| Qui s'y bat ? | `rooms.x.waves[].conditions` | Bob combat si `fact.bob_angry`. |
| Le PNJ est-il là ? | `room_elements.x.vanish_conditions`, `required_item` | `bob_npc` disparaît quand Bob est fâché. |
| Le personnage vient-il en client ? | Conditions du `customer_profile` | `bob_guest` |
| Que répond-il ? | `characters.x.dialogues[]`, par ordre de priorité | `bob_bye` → `bob_fed` → `bob_waiting` → `bob_hungry` |
| Quand une scène part-elle seule ? | `story_triggers.x.conditions` + `place` | « El Tuna, 1re rencontre » |
| Quand un plat, une arme ou un employé se débloque-t-il ? | Conditions de la fiche concernée | Bob recrutable après `fact.bob_joined` |
| Que change une action ou une scène ? | Effets `on_*`, événement `set_value` d'une scène | `quests.bob_hungry_horse.state = 1` |

**Repère rapide** : la salle dit *où* et *si*, le PNJ *qui* et *quoi dire*, le
déclencheur *quand*, la quête tient le *journal* et *l'état*.

### 5.2 Trois sortes de liens, jamais confondues

Chaque sorte a son propre libellé et son propre trait, pas seulement une
couleur :

- **Référence réelle** : « ce PNJ incarne ce personnage », « ce déclencheur
  joue cette scène ».
- **Influence** : « cette scène écrit `fact.bob_angry = true` ; cette règle lit
  `fact.bob_angry` ». C'est une influence, pas une causalité promise.
- **Suite proposée** : lien dessiné par l'auteur dans son plan.

### 5.3 Une identité, plusieurs incarnations

`characters.bob` est incarné par :

- un client, `customer_profiles.bob_guest` ;
- un PNJ, `room_elements.bob_npc` ;
- un combattant, `enemies.bob_the_horse` ;
- un employé, `employees.bob_the_horse`.

Il existe aussi une copie, `employees.bob_the_horse_copy`. Les liens explicites
(le champ `character`) sont repris d'office. Les autres sont **proposés puis
confirmés par l'auteur**, et enregistrés dans le plan.

### 5.4 La quête de Bob, en synthèse

Ce schéma est une synthèse narrative des données, **pas un ordre d'exécution
exhaustif** (repris de l'analyse tierce, taux vérifiés dans le maître) :

```mermaid
flowchart TD
    A[Rencontre dans la salle d'El Tuna<br/>sans Lance-œufs, quête inconnue] --> B[Quête en cours]
    B --> C[Bob client arrive et s'assoit]
    C --> D[Étape 1 du journal]
    D --> E[Servir Bob au restaurant]
    D --> F[Mettre le plat de côté<br/>objet de quête à emporter]
    D --> G[Planque admissible<br/>niveau 3, 50 %]
    F --> H[Parler à Bob avec le plat]
    G --> H
    G --> I[Sans le plat : colère]
    I --> J[Le PNJ disparaît<br/>une vague de combat se réveille]
    J --> K[Excuses après le combat]
    E --> L[Quête réussie]
    H --> L
    L --> M[Lance-œufs donné par un déclencheur]
    M -. chemin attendu .-> N[El Tuna vaincu]
    N --> O[Défi de Bob admissible<br/>niveau 4, 25 %]
    O --> P[Premier duel gagné<br/>Bob devient recrutable]
    P --> Q[Pause de Bob, duel récurrent]
```

### 5.4 bis Le OU

Le moteur lit toujours en ET. Le plan accepte un OU libre, marqué « à
traduire ». Au moment de le réaliser, trois traductions existent déjà :

- plusieurs répliques ;
- plusieurs déclencheurs ;
- un compteur, comme `purchased_parents >= 1`.

Faire évoluer le moteur est une autre décision, hors de ce chantier.

### 5.5 Diagnostics prudents

Chaque avertissement annonce ses limites :

- « aucun producteur déclaré trouvé » pour une adresse lue ;
- « jamais lu » pour une adresse écrite ;
- « réplique masquée » quand une réplique sans condition est placée au-dessus
  d'autres ;
- « scène absente » et « personnage sans incarnation » ;
- « référence disparue » après une actualisation.

Un cycle n'est pas une erreur : les moments répétables en créent volontairement.

---

## 6. Catalogues et sélecteurs

Partout, une entrée **« + à créer »** produit un élément provisoire du plan,
reconnaissable d'un coup d'œil et rattachable plus tard à une vraie fiche.

- **Acteurs** : personnages, avec leurs incarnations.
- **Lieux** : 111 salles groupées par dimension, salles spéciales à part ; plus
  « au restaurant » et « partout ».
- **États** : facts (avec leur portée), état et étape de quête, compteurs
  (`times_talked`, `times_fired`…).
- **Objets** : objets de quête, avec plafond et portée.
- **Récompenses et conséquences**, par intention :

| Intention | Mécanisme réel | Attention |
|---|---|---|
| Donner des pièces | `player.coins` | |
| Donner un matériau | `ingredients.<id>.owned` | |
| Remettre ou reprendre un objet | `key_items.<id>.owned` (+/−) | Plafond et portée de l'objet. |
| Donner une arme | `weapons.<id>.owned` | Possédée n'est pas équipée. |
| Débloquer un plat, un employé | Un fact lu par la condition de la fiche | Recrutable n'est pas embauché. |
| Ouvrir une salle ou une réplique | Un état lu par leurs conditions | Admissible n'est pas garanti. |
| Bonus temporaire | Modificateurs ; les cartes de plongée (`rewards`) en sont un cas | `rewards` n'est **pas** la récompense de quête. |
| Conséquence négative | Colère, objet consommé, quête échouée (`state = 3`), chemin fermé | Toute conséquence n'est pas une récompense. |

Un **ensemble nommé** (« Récompense de Bob ») peut regrouper plusieurs
intentions. Il vit dans le plan seulement : aucune nouvelle collection dans le
schéma.

---

## 7. Les motifs narratifs : écrire avec des briques qui existent

C'est l'apport le plus direct contre les freins. La quête de Bob a déjà éprouvé
une série de **motifs**. L'atelier les propose comme briques à poser sur le
graphe. Chaque brique porte sa traduction dans le moteur, ce qui permet
d'écrire en langage d'auteur tout en restant compatible dès le départ.

| Motif | Traduction dans le moteur | Éprouvé par |
|---|---|---|
| Première rencontre | Réplique conditionnée à `characters.x.times_talked == 0` | Vocabulaire existant |
| Il parle selon l'avancement | Répliques ordonnées sur `quests.x.state` / `stage` et objets possédés | Répliques de Bob |
| Moment à l'entrée d'une salle | Déclencheur sur `rooms.x.current`, lieu donjon | El Tuna, duel |
| Moment répétable (fait réarmé) | Un effet pose un fact ; le déclencheur joue sa scène et le remet à faux | Excuses, fin de pause |
| Variante de salle | `replaces` (dimension, niveau, chance) + conditions de la salle | Planque, défi |
| PNJ qui disparaît et revient en combat | `vanish_conditions` + vague conditionnée au même fact | Colère de Bob |
| Plat à mettre de côté | `set_aside` de la quête → objet de quête → repris dans la scène | Plat de Bob |
| Récompense remise par un moment | `on_fired` qui écrit `weapons.x.owned` | Lance-œufs |
| Il rejoint la brigade | Fact lu par la condition de l'employé | `bob_joined` |
| Un « OU » | Plusieurs répliques ou déclencheurs, ou un compteur | §5.4 bis |

Un motif que le moteur ne sait pas faire reste posable. Il est simplement
marqué « à implémenter moteur », pour que l'écriture ne s'arrête jamais sur une
limite technique.

---

## 8. Créer les vrais éléments sans risque (priorité 4)

Trois marches, franchies seulement si la précédente sert vraiment :

### 8.1 La fiche d'implémentation exportée — recommandée d'emblée

Pour une carte ou une intrigue entière, l'atelier exporte un **Markdown
lisible**. On y trouve :

- les fiches à créer ou modifier, avec des identifiants proposés ;
- les conditions et effets sous forme d'adresses ;
- les motifs utilisés ;
- les textes à écrire ;
- les points « à implémenter moteur » et les questions ouvertes.

Ce document se donne à un agent, ou sert de liste en remplissant les
formulaires. Il suit ensuite le circuit normal : formulaires, validation PHP,
publication, tests. On peut aussi l'associer à une ligne du Sheet.

**C'est la voie qui donne « créer les vrais éléments » avec un risque nul** :
l'atelier n'écrit toujours rien dans le jeu, et le passage au réel garde toutes
ses protections.

### 8.2 L'écriture ciblée au brouillon — plus tard, si l'usage la réclame

Un garde-fou existe déjà : l'autosauvegarde du gestionnaire envoie l'empreinte
du brouillon qu'elle connaît et **refuse (409) si le fichier a changé
ailleurs**.

Une écriture future passerait donc par ce même point d'entrée, en quatre temps :

1. lire le brouillon ;
2. appliquer une modification **limitée et montrée avant** (fiches et champs
   concernés) ;
3. renvoyer le tout avec l'empreinte lue, pour obtenir la validation complète
   `validate_and_normalize` ;
4. laisser la publication dans le gestionnaire.

Un onglet du gestionnaire resté ouvert recevrait alors le refus et
demanderait de recharger, au lieu d'écraser.

Avant d'ouvrir cette marche, il faudra des essais dédiés : priorités des
répliques, portées, localisation, compteurs calculés (jamais écrits),
déclencheurs répétés.

### 8.3 L'éditeur narratif publiable — non recommandé

Répartir automatiquement un segment d'auteur entre quête, déclencheurs,
répliques, salle et effets est une traduction, pas un export. La fiche
d'implémentation (8.1) fait ce travail avec un humain ou un agent dans la
boucle. C'est plus sûr, et presque aussi rapide.

---

## 9. Interface proposée

Une page **Atelier narratif** dans son propre dossier du gestionnaire, servie
par le même serveur PHP local, avec trois zones :

- **À gauche, la bibliothèque** : intrigues, personnages, salles, scènes,
  objets, récompenses, **motifs**. Recherche par nom ; glisser une référence ou
  un motif sur le graphe ; « + nouvelle idée ».
- **Au centre, le graphe** : vue centrée sur une intrigue ou un personnage. Le
  détail technique reste replié tant qu'on ne le demande pas ; une vue de tout
  le jeu à la fois n'est pas l'écran de départ.
- **À droite, l'inspecteur**. Il montre :
  - titre, résumé et texte ;
  - acteurs, lieux, déclenchement, conditions (avec leur emplacement réel) ;
  - conséquences et récompenses ;
  - portée, répétition, priorité, probabilité ;
  - échelon de maturité et provenance (fiche, champ, publié ou brouillon) ;
  - un bouton vers la fiche source dans le gestionnaire.

En haut : un sélecteur **Publié / Brouillon** avec l'heure de lecture, un
bouton **Actualiser** (qui préserve positions, notes et idées) et les exports
**Markdown** et **JSON**.

**Repris de Taskmaster** :

- l'ergonomie des cartes : déplacer, redimensionner, zoom, grille ;
- les connexions SVG, les couleurs d'intrigue et les filtres ;
- le suivi `!!` / `%%` ;
- les sélecteurs à multi-sélection avec « + Nouveau » ;
- annuler / refaire, dupliquer.

**Laissé de côté** :

- la couche de données de Taskmaster : champs doublés, liens par titres,
  rapprochements par `includes`, import/export encore branché sur l'ancienne
  API ;
- le scheduler et la temporalité en secondes ;
- l'autosauvegarde qui réécrit un maître entier.

### Références durables dans le plan

Une référence enregistre **collection + identifiant**, jamais le nom affiché.
Pour les sous-éléments repérés par leur position (étapes du journal, rang de
réplique), le plan garde aussi une **empreinte du contenu**. Si cette empreinte
ne correspond plus, l'atelier demande une réconciliation au lieu de rattacher
une note au mauvais élément.

---

## 10. Découpage en étapes

Chaque étape doit être **utile seule**, et on peut s'arrêter après n'importe
laquelle.

1. **Bob, en lecture.**
   - Contenu : la page, la lecture Publié / Brouillon, l'index des références
     de Bob, les trois sortes de liens, l'inspecteur avec provenance, les
     positions enregistrées dans le plan.
   - Contrôle : le test des garanties (§3), empreintes avant/après.
   - Question à trancher : comprend-on mieux Bob, et retrouve-t-on vite la
     règle qu'on cherche ?
2. **Écrire une intrigue neuve.**
   - Contenu : cartes libres, échelle de maturité, éléments « à créer »,
     sélecteurs réels, liens proposés, `!!` / `%%`, annuler / refaire,
     recherche.
   - Question à trancher : peut-on écrire une deuxième intrigue entière sans
     ouvrir le gestionnaire ?
3. **Motifs et fiche d'implémentation.**
   - Contenu : la bibliothèque de motifs et l'export Markdown.
   - Question à trancher : la fiche suffit-elle à réaliser une quête sans aller
     et retour ?
4. **Diagnostics et vue élargie.** Les autres personnages et salles,
   l'actualisation avec références disparues, la comparaison publié /
   brouillon.
5. *(Optionnelle)* **Écriture ciblée au brouillon** selon §8.2, seulement si
   les étapes 1 à 4 servent au quotidien.

Validation : tests JS et PHP ciblés dans `tools/game-data-manager/tests/`.
**Aucun contrôle Godot n'est nécessaire**, puisque rien de Godot n'est touché.

---

## 11. Critères de réussite de la première version

1. Rien d'existant n'a bougé : empreintes identiques ; `app.js`, `api.php` et
   `config.php` inchangés (hors lien facultatif).
2. On comprend la quête de Bob depuis une vue synthétique, puis on descend
   jusqu'au champ réel qui porte chaque règle.
3. Une intrigue imaginaire complète s'écrit avec des acteurs, lieux et
   récompenses « à créer », sans identifiant à taper.
4. Idées, liens réels et influences calculées restent visuellement
   distinguables.
5. Une actualisation préserve le travail et signale ce qui a disparu.
6. On sait toujours si l'on regarde le publié ou le brouillon.

---

## 12. Décisions à prendre ensemble

| Sujet | Proposition |
|---|---|
| Emplacement | Page dédiée dans son propre dossier ; un lien facultatif dans le gestionnaire. |
| Premier écran | **Voir Bob** (étape 1) ou **écrire tout de suite** une nouvelle intrigue (étape 2 d'abord) ? |
| Passage au réel | Fiche d'implémentation exportée ; écriture au brouillon repoussée. |
| Récompenses | Sélecteur par intention ; ensembles nommés dans le plan seulement. |
| OU | Libre dans le plan, marqué « à traduire ». |
| Première intrigue neuve | Laquelle ? (KMLD, Musicalo, MLD, fil des dimensions 1 à 4…) |

---

## 13. Références

- Jeu :
  - [maître publié](../data/game_data_master.json) ;
  - [brouillon](../tools/game-data-manager/data/draft.json) ;
  - [catalogue d'adresses](../scripts/core/address_catalog.gd) ;
  - [déclencheurs](../scripts/core/story_triggers.gd) ;
  - [GameState](../autoload/game_state.gd).
- Gestionnaire :
  - [api.php](../tools/game-data-manager/api.php) : `load`, `load_master`, et
    `autosave` avec son refus 409 ;
  - [app.js](../tools/game-data-manager/assets/app.js) : `questEditor`,
    `characterEditor`, `storyTriggerEditor`, `storyWritableAddresses` ;
  - [config.php](../tools/game-data-manager/config.php) : validation.
- Taskmaster, dossier
  `chrono island/GODOT/chrono-island/Taskmaster3000/` :
  - `narrative/js/canvas.js`, `connections.js`, `narrative-sidebar-v2.js`,
    `selection-popups.js` ;
  - `core/data/master.json` : 175 segments, 38 acteurs, 13 intrigues, 437
    facts.
