Décrire le cycle de vie dans le README, et l'illustrer

Le jeu de démonstration reçoit trois projets sans phase — un envisagé,
un dont l'horizon est passé, un écarté — sans quoi la fonctionnalité
reste invisible à qui découvre l'outil.

Corrige aussi « node --test tests/ », que Node 26 refuse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 14:58:36 +02:00
parent 60a91ba5b2
commit d6f3b2961b
2 changed files with 138 additions and 10 deletions

114
README.md
View File

@@ -65,7 +65,7 @@ alors `data/projets.json`, comme avant.
```sh
go test ./... # le serveur
node --test tests/ # le modèle métier
node --test # le modèle métier
```
## Prise en main
@@ -75,13 +75,18 @@ ce nom présélectionné : on tape simplement par-dessus. Il n'y a aucun formula
ici, ni pour une phase. Tout s'applique au fil de la saisie, et un projet créé par erreur se
supprime depuis son propre panneau.
Il naît **envisagé** : sans phase, avec pour seul ancrage un horizon d'un mois, celui où on le
crée. On le repousse à sa place, et on l'engage le jour où on lui donne des dates fermes — voir
[le cycle de vie](#le-cycle-de-vie-dun-projet) juste en dessous.
Dans la colonne de gauche, le **triangle** plie et déplie le couloir d'un projet, et un clic sur
son **nom** ouvre ses paramètres : nom, couleur, tags. Deux commandes apparaissent au survol de
la ligne, sur son bord droit :
son **nom** ouvre ses paramètres : nom, couleur, tags, horizon. Deux commandes apparaissent au
survol de la ligne, sur son bord droit :
- **`+`** ajoute une phase à la suite de la dernière, et ouvre son panneau de détail ;
- **`⋯`** ouvre le menu du projet : ajouter une phase, plier, masquer de la frise, renommer,
figer la référence, supprimer. Un clic droit sur le libellé ouvre le même menu.
déclarer terminé, écarter, figer la référence, supprimer. Un clic droit sur le libellé ouvre le
même menu.
Il n'y a pas de commande séparée pour créer un **jalon** : c'est une phase dont on coche la case
« Jalon » dans le panneau, ce qui ramène sa fin sur son début. La bascule joue dans les deux sens
@@ -96,6 +101,7 @@ Une fois un projet en place :
| Geste | Effet |
|---|---|
| Glisser le corps d'une barre | Décale la phase, durée conservée |
| Glisser la barre pâle d'un envisagé | Décale son horizon, au mois |
| Glisser le bord d'une barre | Change la date de début ou de fin |
| Glisser le bord gauche du panneau | Change sa largeur (double-clic : d'origine) |
| Clic sur une barre ou son nom | Ouvre le panneau de détail |
@@ -111,6 +117,65 @@ Une fois un projet en place :
Faire défiler jusqu'au bord droit élargit la frise vers le futur, et jusqu'au bord gauche
vers le passé. Le bouton **Aujourd'hui** ramène la vue sur la date du jour.
### Le cycle de vie d'un projet
On a presque toujours plus de projets imaginables que de temps pour les mener, et l'enjeu n'est pas
de les oublier en attendant. Un projet traverse donc quatre états, dont **deux se déduisent tout
seuls** — il n'y a rien à tenir à jour :
| État | Comment on le sait |
|---|---|
| **Envisagé** | il n'a qu'un horizon, pas encore de phase |
| **Engagé** | on lui a donné au moins une phase datée |
| **Terminé** | toutes ses phases sont finies **et** on l'a acté |
| **Écarté** | on a décidé de ne pas le faire |
Le flux tient en une phrase : **une idée entre avec un horizon, on la situe, on l'engage en lui
donnant des dates, elle vit sur la frise, elle s'achève ou on l'écarte.**
Engager n'est donc pas un bouton, c'est un geste : ajouter la première phase. Terminer et écarter,
eux, s'actent — livré n'est pas clos, et abandonner est une décision. Leurs deux commandes sont au
bas du **panneau du projet**, sous le champ qui dit où il en est, et aussi dans son menu **`⋯`**.
**Déclarer un projet terminé termine aussi toutes ses phases**, jalons compris : sans quoi la frise
se contredirait, avec des tâches « à venir » dans un projet fini. C'est la seule opération du cycle
qui écrase quelque chose — le statut d'une phase bloquée est perdu, et rouvrir le projet ne le
rendra pas. Elle demande donc confirmation, mais seulement s'il reste des phases à changer.
#### L'horizon
Un projet envisagé n'est jamais hors du temps : il porte un **horizon en mois** — « mars 2027 »,
« de mars à septembre 2027 », « courant 2028 » — et il se pose **sur la frise**, à cet horizon.
C'est là que l'arbitrage devient concret : quand le printemps 2027 est déjà chargé et que six
barres pâles s'y superposent, on décide devant l'évidence.
Sa barre est hachurée et ses bords sont fondus, parce que ces dates ne sont pas fermes. Elle se
glisse et se redimensionne comme une barre de phase, mais **accrochée au mois** là où celle d'une
phase l'est au lundi : le geste est possible, il ne permet simplement pas de poser une date qu'on
n'a pas. Le panneau du projet offre en plus trois crans — `3 mois`, `+3 mois`, `+1 an` — et les
deux mois au clavier.
La largeur de la barre *est* l'incertitude, et elle se resserre à mesure que le projet mûrit :
d'abord une plage large, puis un mois, puis les dates fermes de l'engagement.
**Engager démarre à l'horizon** : la première phase d'un projet envisagé naît au premier jour de son
horizon, là où la barre pâle commençait. On précise ensuite ses dates comme n'importe quelle phase.
Un projet dont l'**horizon est passé** — ou qui n'en a jamais eu — le dit sur sa ligne, par une
pastille **« à dater »**. C'est ce qui empêche la liste des envisagés de devenir une décharge : on
repousse, ou on écarte, mais on ne laisse rien dormir.
#### Écarter n'est pas supprimer
Un projet écarté quitte la frise, mais il garde tout — notes comprises, où l'on aura écrit
pourquoi on a dit non. Les mêmes idées reviennent tous les deux ans, portées par d'autres, et
savoir qu'on les a déjà examinées vaut mieux que de refaire le débat.
On le retrouve en cochant **Écartés** dans la barre *Afficher*, et **Remettre en jeu** l'en sort. Il
n'y a alors aucune destination à choisir : le projet retrouve seul l'état que ses données
commandent — engagé s'il a des phases, envisagé sinon. Son horizon étant resté celui d'avant, il
réclamera aussitôt une date, et c'est voulu.
### Au clavier, à la vim
La frise a un **curseur** : la ligne sur laquelle portent les raccourcis. Il se pose en cliquant une
@@ -188,6 +253,12 @@ liste, projets mêlés, groupés par mois — celui où chaque phase **commence*
« qu'est-ce qui arrive le mois prochain », que la frise donne mal parce qu'elle sépare les projets
en couloirs.
Les **projets sans phase** y figurent aussi, au premier mois de leur horizon : un projet visé pour
mars 2027 arrive bel et bien en mars 2027, et la liste répond à « qu'est-ce qui arrive », pas à
« qu'est-ce qui est déjà décidé ». Leur ligne occupe les mêmes colonnes, en italique, et porte
« Envisagé » là où les autres portent leur statut. Un projet **écarté** avant d'avoir jamais été
engagé s'y retrouve de la même façon — barré, et seulement si l'on a coché *Écartés*.
Chaque ligne se lit dans cet ordre : quand — la période, `31 → 13 nov.` quand la phase déborde du
mois —, chez qui — le projet et ses tags —, puis quoi — l'intitulé de la tâche ou du jalon — et
enfin son statut. Une phase longue n'est **pas** répétée dans les mois qu'elle traverse : elle
@@ -224,10 +295,27 @@ portant les deux. Le filtre n'est pas enregistré, il ne vaut que pour la sessio
Les barres s'accrochent au lundi pendant le glisser. Pour une date au jour près, passer
par les champs du panneau de détail.
### Afficher par état
Une seconde barre, **Afficher**, paraît au-dessus dès que le planning compte plus d'un état. Elle
montre chacun avec son compte — *Envisagés (4)*, *Écartés (7)* — et un clic l'affiche ou le masque.
Les écartés en sont décochés au départ : le cimetière ne s'ouvre que si on le demande.
Elle ne joue **pas** dans le même sens que le filtre par tags, et c'est pourquoi elle ne lui
ressemble pas : un projet porte plusieurs tags mais un seul état, si bien que cocher un tag de plus
resserre la sélection quand cocher un état de plus l'élargit. D'où « Filtrer » d'un côté, « Afficher »
de l'autre, et des boutons carrés plutôt que des pastilles. Comme le filtre par tags, celui-ci vaut
pour les deux vues et n'est pas enregistré.
## Ce que fait l'outil
- **Plusieurs projets**, chacun décomposé en **phases** ayant un nom, des dates de début et de fin,
un statut, des notes. Une phase peut être un **jalon** (une date unique, rendue en losange).
- **Un cycle de vie** — envisagé, engagé, terminé, écarté — dont deux états se déduisent des
données. Ce qu'on envisage sans pouvoir encore le mener vit sur la même frise que le reste, et
ne s'y perd pas.
- **Un horizon en mois** pour les projets envisagés, rendu en barre hachurée aux bords fondus : la
largeur dit l'incertitude, et un horizon dépassé réclame de lui-même qu'on tranche.
- **Des notes en markdown**, sur un projet comme sur une phase : titres, listes, cases à cocher,
liens. Elles occupent toute la hauteur restante du panneau, et se cochent d'un clic dans l'aperçu.
- **Une frise commune**, les projets empilés en couloirs, pour les comparer d'un coup d'œil.
@@ -249,7 +337,7 @@ par les champs du panneau de détail.
- **Une vue par mois** : toutes les tâches et tous les jalons en une liste, projets mêlés, groupés
par mois de début. Elle se lit, elle ne s'édite pas.
- **Des tags sur les projets**, et un filtre qui restreint les deux vues à ceux qui les portent
tous.
tous — doublé d'un affichage par état, qui joue lui en sens inverse.
- **Repère « aujourd'hui »** et masquage d'un projet.
## Ce que l'outil ne fait pas
@@ -257,6 +345,11 @@ par les champs du panneau de détail.
Volontairement : pas de dépendances entre phases, pas de sous-tâches, pas de collaboration temps
réel, pas d'authentification, pas de gestion de charge par personne, pas de notifications.
**Pas de note de priorité non plus, ni de matrice.** L'arbitrage passe par l'horizon : dire « celui-ci
au printemps, celui-là on verra en 2028 » *est* la décision, et un score posé à côté des dates se
périmerait en silence. Ce qui manque encore, c'est le départage fin entre deux projets visant le même
trimestre — il attend d'avoir un endroit où ranger, la frise sachant situer mais pas ordonner.
Les durées se comptent en **jours calendaires** : ni week-ends ni jours fériés ne sont gérés. À
l'échelle de phases de plusieurs semaines, la distinction n'apporte rien.
@@ -308,8 +401,9 @@ node --test # la logique métier
go test ./... # le serveur
```
Côté navigateur : validation des dates, bornes d'un projet, calcul de dérive, génération des
identifiants, normalisation et filtrage des tags, regroupement des phases par mois. Côté serveur : lecture et écriture du planning,
Côté navigateur : validation des dates et des horizons, bornes et emprise d'un projet, calcul de
dérive, génération des identifiants, normalisation et filtrage des tags, regroupement des phases par
mois, dérivation de l'état d'un projet et transitions de son cycle de vie. Côté serveur : lecture et écriture du planning,
refus des corps invalides, rotation des sauvegardes, écriture atomique, résolution du chemin de
données. Aucune dépendance de part ni d'autre, les lanceurs intégrés à Node et à Go suffisent.
@@ -319,12 +413,12 @@ données. Aucune dépendance de part ni d'autre, les lanceurs intégrés à Node
|---|---|
| `main.go` | Sert l'interface embarquée, expose `GET`/`PUT` sur `/api/data`, écrit les sauvegardes |
| `build.sh` | Compile les binaires des cinq plateformes dans `dist/` |
| `js/model.js` | Données et règles métier : CRUD, validation, bornes, référence, dérive, tags, regroupement par mois |
| `js/model.js` | Données et règles métier : CRUD, validation, bornes, cycle de vie et horizon, référence, dérive, tags, regroupement par mois |
| `js/storage.js` | Dialogue avec le serveur, sauvegarde debouncée, indicateur d'état |
| `js/timeline.js` | Rendu de la frise : échelle, couloirs, barres, jalons, pli/dépli, curseur |
| `js/mois.js` | Rendu de la vue par mois : groupes, lignes, ancrage sur le mois courant |
| `js/mois.js` | Rendu de la vue par mois : groupes, lignes de phase et de projet envisagé, ancrage sur le mois courant |
| `js/tags.js` | Pastilles de tags, partagées par les deux vues |
| `js/drag.js` | Glisser et redimensionner les barres |
| `js/drag.js` | Glisser et redimensionner les barres — au lundi pour une phase, au mois pour un horizon |
| `js/clavier.js` | Table des raccourcis à la vim, préfixes `g` `z` `d`, garde-fou de saisie |
| `js/markdown.js` | Analyse du markdown des notes, aplatissement pour les infobulles. Sans DOM, donc testable sous Node |
| `js/notes.js` | Rendu du markdown en DOM et bloc de notes — aperçu, barre d'outils, saisie — partagé par les deux panneaux |