Files
kanbante/CHANGELOG.md
T

394 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
## 0.12.0 — 2026-10-11
### Nouveautés
- **Focus du jour** (issue #5) : le rituel des 3 cartes. Table
`today_picks` ; bouton 📌 sur chaque carte du board (et sur les
candidates) ; page `/today` calme — picks du jour avec leur
colonne en direct, candidates de l'encours, **reprises d'hier
non terminées** reproposées, récapitulatif « ça a bougé
aujourd'hui » tiré du journal. Le briefing du matin inclut les
sections « Focus du jour » et « À reprendre d'hier ».
`POST /api/today/pin` (max 3, idempotent) et `/unpin`.
- **Prévisions** (issue #7) : `app/forecast.py` — fermetures par
semaine depuis le journal (8 semaines), débit moy/min/max sur
les 4 dernières semaines complètes, projection en **fourchette**
(jamais un faux chiffre précis) et silence explicite sans
historique. Affichées sur le dashboard (épuisement du backlog),
dans le bandeau milestone (avec alerte si l'ETA dépasse
l'échéance) et sur `/forecast` (sparkline SVG inline, verdict
par milestone). `/api/metrics` expose `weekly_closures` et
`throughput_4w`.
- **Récit de sprint** (issue #4) : `app/sprint.py` + page
`/sprint/{owner}/{repo}?milestone=` — le bilan markdown du
milestone écrit par le journal : livré (avec temps de cycle par
carte), cartes les plus lentes, reporté avec colonnes, chiffres
de la période ; boutons **Copier** et **Télécharger .md**,
endpoint `GET /api/sprint/...` en JSON, lien « 📖 Récit de
sprint » dans le bandeau milestone du board.
11 tests ajoutés (147 au total).
## 0.11.0 — 2026-10-11
### Nouveautés
- **Wallboard navigable** : flèches `←` / `→` du clavier, boutons
❮ ❯ et pastilles cliquables pour changer de projet à la demande ;
une navigation manuelle met la rotation en pause 90 s, `Espace`
bascule une pause franche (badge visible). La **position est
mémorisée** (sessionStorage) entre les rechargements : le mur ne
repart plus à la première diapo à chaque refresh — avec 12
projets actifs × 30 s, le cycle complet (6 min) dépassait le
rechargement de sécurité (5 min), rendant les dernières diapos
inatteignables et donnant l'impression d'un mur figé.
### Correction
- L'écoute temps réel du wallboard utilisait `onmessage`, qui ne
se déclenche jamais pour les événements SSE **nommés** (`gitea`)
émis par le hub : les rechargements en direct ne partaient pas,
seul le filet de 5 minutes fonctionnait. Corrigé en
`addEventListener('gitea', …)`.
3 tests ajoutés (136 au total).
## 0.10.0 — 2026-10-11
### Nouveautés
- **Mode Triage** (issue #11) : vider un backlog au clavier, façon
« inbox zero ». `/triage` liste les projets actifs et la taille
de leur backlog ; `/triage/{owner}/{repo}` présente les cartes
du Backlog **une par une, plein cadre** (titre, extrait du corps,
étiquettes, âge), file embarquée côté client — aucun rechargement
entre cartes. Décisions : `1`–`5` envoient dans À faire / En
cours / QA / Révision / Terminé, `X` ferme, `L` ouvre le panneau
d'étiquettes (bascule via l'API existante), `A` s'assigne l'issue
(nouvel endpoint `POST /api/issues/{o}/{r}/{n}/assign-self`,
idempotent), `Entrée` passe à la suivante, `Z` annule le dernier
déplacement. Barre de progression « Carte n / N » et résumé final
par décision. Les raccourcis sont affichés en permanence et
cliquables. Points d'entrée : bouton « Triage du backlog » sur le
board et action dans la palette Ctrl+K.
6 tests ajoutés (133 au total).
## 0.9.0 — 2026-10-11
### Nouveautés
- **Board dynamique sans refresh** (issue #15) : le board reflète
l'état réel en continu. Côté serveur, chaque mutation connue
(déplacement, création, capture, bascule d'étiquette) est
désormais diffusée sur le hub SSE — jusqu'ici seuls les webhooks
émettaient — et les webhooks bénéficient du même canal pour
toutes leurs actions (étiquettes, créations, éditions comprises).
Nouvel endpoint `GET /api/board/{owner}/{repo}` : état du board
en JSON avec les cartes **rendues côté serveur** (partiel
`_card.html` partagé avec la page), même pipeline de
réconciliation/adoption que le board HTML. Côté client,
`board-live.js` applique le **diff en place** (seules les
colonnes changées sont remplacées, signature par colonne),
anime les cartes survivantes vers leur nouvelle place (FLIP,
désactivé si `prefers-reduced-motion`), diffère l'application
pendant un drag local, réapplique filtres/compteurs/indices, et
**sonde toutes les 45 s** en repli (installations sans webhooks,
onglet visible). Ni le défilement, ni le panneau détail, ni
Sortable ne sont affectés. Focus et Wallboard conservent leur
recharge douce, désormais déclenchée par toutes les mutations.
6 tests ajoutés (127 au total).
## 0.8.0 — 2026-10-11
### Nouveautés
- **Palette de commandes** (issue #10) : `Ctrl+K` / `Cmd+K` (ou le
bouton ⌨️ dans la navigation) ouvre sur toutes les pages une
palette façon Linear/Raycast — actions de navigation, tous les
projets (filtrage local instantané) et recherche globale d'issues
annotées de leur colonne (nouvel endpoint `GET /api/palette?q=`).
Navigation entièrement au clavier (↑↓, Entrée, Échap).
- **Digest hebdo vers ObsiGate** (issue #13) : le résumé markdown
de la semaine (issues fermées enrichies de leurs titres, cartes en
cours/QA/révision, compteurs du journal) est composé
automatiquement le jour et l'heure choisis
(`KANBANTE_DIGEST_WEEKDAY` / `KANBANTE_DIGEST_TIME`) avec
notification ntfy — mais **jamais livré sans approbation** :
l'envoi se fait d'un clic sur `/digest`, vers le serveur MCP
d'ObsiGate (client MCP intégré : initialize + tools/call ; URL,
jeton, nom d'outil et gabarit JSON d'arguments configurables ;
bouton « Tester la connexion » qui liste les outils du serveur)
ou vers un webhook générique (`KANBANTE_DIGEST_WEBHOOK_URL`,
JSON `{title, markdown, week}`).
11 tests ajoutés (121 au total).
## 0.7.0 — 2026-10-11
### Nouveauté
- **Capture éclair** (issue #12 de la feuille de route) : trois
entrées, un seul geste — transformer un message en issue placée
sur le board (événement `created`, source `capture`) :
- `POST /api/capture` : endpoint machine-à-machine protégé par un
**jeton de capture dédié** (`KANBANTE_CAPTURE_TOKEN`, en-tête
`X-Capture-Token` ou Bearer ; distinct du jeton Gitea, révocable
seul ; désactivé en 503 tant qu'il n'est pas défini ; exempté
d'auth Basic et de CSRF). JSON `{title, body, repo, column}` ou
texte libre (première ligne = titre). Dépôt par défaut :
`KANBANTE_CAPTURE_REPO`.
- **Écoute ntfy** : si `KANBANTE_CAPTURE_NTFY_TOPIC` est défini,
un abonné en tâche de fond (flux JSON du topic, reconnexion avec
recul, curseur persisté dans `kv_store` — aucun rejeu au
redémarrage) transforme chaque message en issue. Les messages
tagués `kanbante` sont ignorés (pas d'auto-ingestion).
- Page **`/capture`** : formulaire de saisie rapide, statut de
configuration et exemples prêts à copier (curl, ntfy). Lien
« ⚡ Capture » dans la navigation de toutes les pages.
12 tests ajoutés (110 au total).
## 0.6.0 — 2026-10-11
### Nouveautés
- **Colonne QA** entre « En cours » et « Révision » (🧪, étiquette
`kanban:qa`) : une étape de validation finale avant la révision.
Le flux complet devient Backlog → À faire → En cours → QA →
Révision → Terminé ; la vue Focus inclut les cartes en QA.
- **Wallboard** (issue #14 de la feuille de route) : `GET /wall`,
affichage plein écran pensé pour un écran d'atelier — rotation
automatique (30 s) entre les projets actifs, compteurs des six
colonnes, cartes en vol (En cours / QA / Révision / À faire) avec
âge, fermées du jour, horloge ; rafraîchissement en direct via le
flux SSE. `?repo=Proprietaire/depot` fige un seul projet. Lien
« 🖥️ Wallboard » ajouté à la navigation de toutes les pages.
- **Réconciliation par étiquettes** : si l'étiquette `kanban:*` d'une
issue ouverte diverge de sa colonne enregistrée (modifiée dans
Gitea ou par un autre outil), le board et la vue Focus adoptent la
colonne de l'étiquette et journalisent le déplacement (source
`gitea`). Règles : exactement une étiquette `kanban:*` fait foi ;
zéro ou plusieurs = l'état local gagne ; inactif si
`KANBANTE_SYNC_LABELS=0`. Déplacer une carte depuis Gitea devient
donc possible.
10 tests ajoutés (98 au total).
## 0.5.2 — 2026-10-11
### Correctif
- **L'indice « Glissez une carte ici » restait affiché après un
dépôt dans une colonne vide** : il est rendu par le serveur pour
les colonnes vides au chargement, et le glisser-déposer ne le
retirait jamais du DOM. `refreshEmptyHints()` recalcule désormais
l'indice d'après le contenu réel de chaque colonne après tout
déplacement (et après un retour arrière en cas d'échec) : retiré
dès qu'une carte est présente, rétabli quand la dernière carte
part. SortableJS est en outre restreint aux seules cartes
(`draggable: '.kanban-card'`), l'indice n'est plus un élément
déplaçable parasite.
## 0.5.1 — 2026-10-11
### Correctif critique
- **Les boards étaient vides contre un vrai Gitea** : l'API Gitea
(1.27.3 vérifié) renvoie la clé `"pull_request": null` sur les
issues ordinaires ; le filtre `_is_issue` testait la *présence* de
la clé (`"pull_request" not in item`), donc chaque vraie issue
était classée « pull request » et écartée. Board, vue Focus et
briefing ne montraient aucune carte (le dashboard, qui lit les
compteurs des dépôts, semblait normal). Corrigé : le filtre teste
la *valeur* (`not item.get("pull_request")`).
- Le faux Gitea des tests omettait la clé, ce qui masquait le bug :
il reproduit désormais fidèlement le payload réel (clé toujours
présente, `null` sur les issues), plus 4 tests de régression dédiés
(88 tests au total). Smoke test réel : le board `bruno/flowdeck`
passe de 0 à 6 cartes, dont l'issue de test « test d'ajout ! ».
## 0.5.0 — 2026-10-11
« Palier 3 » (points 7 à 9) + board enrichi.
### Ajouts
- **Recherche globale** (`/search`) : recherche d'issues dans tous les
projets via l'API Gitea, résultats groupés par projet avec la colonne
Kanban de chaque issue. **Mes issues** (`/my`) : les issues ouvertes
assignées à l'utilisateur du jeton, tous projets confondus.
- **Briefing quotidien** : page `/briefing` (encours, activité 24 h,
cartes vieillissantes, milestones proches), `GET /api/briefing`, et
envoi **ntfy** manuel (`POST /api/briefing/send`) ou automatique à
`KANBANTE_BRIEFING_TIME` via un planificateur interne (mémoire
d'envoi en base, aucun doublon après redémarrage).
- **Serveur MCP** (lecture seule) : JSON-RPC 2.0 sur `POST /mcp`
(initialize, tools/list, tools/call, ping) avec 7 outils —
`list_projects`, `get_board`, `get_issue`, `get_focus`,
`search_issues`, `get_activity`, `get_metrics`. Aucune écriture,
conformément au principe « lectures d'abord ». `GET /mcp` décrit le
serveur.
- **Gestion des étiquettes sur le board** : modale de gestion
(lister / créer avec palette de couleurs / supprimer les étiquettes
du dépôt dans Gitea) et, dans le panneau détail, ajout / retrait
d'étiquettes sur l'issue en un clic, avec mise à jour immédiate de
la carte. API : `GET|POST /api/repos/{o}/{r}/labels`,
`DELETE /api/repos/{o}/{r}/labels/{id}`,
`POST /api/issues/{o}/{r}/{n}/labels`.
### Améliorations
- **Panneau Notes du projet** : repliable (bouton ⤢, état mémorisé par
projet), **largeur ajustable** par glisser (mémorisée), et
**sauvegarde automatique** après 1,2 s sans frappe avec indicateur
d'état (le bouton manuel reste). Le formulaire quitte HTMX pour le
même `board.js` que le reste du board.
- Navigation unifiée enrichie sur toutes les pages : Mes issues,
Briefing, Recherche.
### Tests
- 19 tests ajoutés (84 au total) : recherche et mes issues, briefing
(page, API, envoi ntfy, format), protocole MCP, API étiquettes,
marqueurs du board. Un doublon de déclaration JS attrapé par
`node --check` avant livraison.
## 0.4.0 — 2026-10-11
« Palier 2 » : temps réel et visible dans Gitea — plus une refonte
complète de l'interface.
### Ajouts
- **Webhooks Gitea + rafraîchissement en direct** : `POST /webhooks/gitea`
(signature HMAC-SHA256 vérifiée quand `KANBANTE_WEBHOOK_SECRET` est
défini) invalide le cache de lecture, applique les fermetures /
réouvertures faites dans Gitea (idempotent : l'écho de nos propres
appels ne double jamais le journal) et pousse un événement SSE sur
`GET /api/stream`. Le navigateur se recharge en douceur quand c'est
sûr (onglet visible, pas de panneau ouvert, pas de saisie en cours,
pas de drag) ; sinon une pastille « Nouvelle activité » propose
l'actualisation.
- **Synchro par étiquettes** : les colonnes intermédiaires sont
reflétées dans Gitea par des étiquettes `kanban:todo`,
`kanban:in_progress`, `kanban:review` (créées au besoin, ajout /
retrait granulaires — les étiquettes de l'utilisateur ne sont jamais
touchées ; backlog et done = aucune étiquette). Désactivable :
`KANBANTE_SYNC_LABELS=0`.
- **Boards par milestone** : `GET /board/{owner}/{repo}?milestone=<titre|id>`
filtre le board, avec bandeau d'échéance et progression
(issues fermées du milestone / total). Sélecteur de milestones
au-dessus du board.
### Interface (refonte complète)
- Nouveau design system : en-tête vitré sticky avec navigation en
pastilles (état actif), halos d'ambiance, cartes projets qui se
soulèvent au survol, barres de progression, coins plus doux,
anneau de focus visible partout, `prefers-reduced-motion` respecté.
- Dashboard : hero avec tuiles de synthèse (projets actifs, issues
fermées et déplacements sur 30 jours, temps de cycle moyen — depuis
le journal), états vides guidés pour chaque onglet, raccourci `/`
pour la recherche (aussi sur le filtre du board).
- Board : pastille « live » en cas d'activité externe, colonnes à
défilement indépendant, placeholders de colonnes vides, panneau de
notes explicité, drawer animé.
- Cohérence : même navigation sur les 5 pages, responsive retravaillé.
### Tests
- 13 tests ajoutés (65 au total) : hub SSE et générateur de flux,
webhooks (transition, idempotence, signature, JSON invalide),
synchro d'étiquettes, boards par milestone, marqueurs de la refonte.
## 0.3.0 — 2026-10-11
« Palier 1 » : voir ce qui se passe sur les boards.
### Ajouts
- **Journal d'événements** (`board_events`, append-only) : chaque
création, déplacement, fermeture, réouverture et commentaire est
horodaté. Il alimente la page **`/activity`** (fil tous projets),
`GET /api/events` et `GET /api/metrics` (débit par type et temps de
cycle moyen : entrée en « En cours » → fermeture). Les fermetures
détectées lors de la réconciliation avec Gitea sont aussi journalisées
(source `gitea`). Un reclassement dans la même colonne n'écrit pas
d'événement.
- **Panneau détail de carte** : un clic sur une carte ouvre un panneau
latéral avec le corps de l'issue rendu en markdown (marked + DOMPurify,
vendorés), ses commentaires, assignés, milestone et échéance ; on peut
**commenter directement dans Gitea** depuis le panneau
(`GET /api/issues/{owner}/{repo}/{n}`, `POST .../comments`, 404 propre
si l'issue n'existe pas).
- **Vieillissement des cartes** : badge « ⏳ N j » dès qu'une carte reste
dans sa colonne au-delà de `KANBANTE_AGING_DAYS` (défaut 7, rouge au
double). Le temps en colonne vient du journal, avec repli sur
`board_state.updated_at` puis sur la date de création de l'issue.
- **Limites WIP** : `KANBANTE_WIP_LIMITS="in_progress:5,review:3"` —
l'en-tête de colonne affiche `n/limite`, passe en rouge en dépassement
et un toast avertit au dépôt. Limites souples : jamais bloquantes.
### Tests
- 16 tests ajoutés (52 au total) : journal et métriques, détail et
commentaires, vieillissement, WIP.
## 0.2.0 — 2026-10-11
Consolidation complète à partir d'un audit du code 0.1.0 (chaque correctif
marqué « confirmé » avait été reproduit par un test avant correction).
### Critiques corrigés
- **Perte de données en Docker** : `KANBANTE_DB_PATH` est enfin lue par le
code — la base SQLite atterrit dans le volume `/data` comme prévu.
- **Authentification** : Basic Auth optionnelle mais recommandée
(`KANBANTE_AUTH_USER` / `KANBANTE_AUTH_PASSWORD`, `KANBANTE_REQUIRE_AUTH=1`
pour refuser de servir sans), protection CSRF (double-submit) sur tous
les POST, avertissement bruyant au démarrage quand l'auth est absente.
- **Synchro bidirectionnelle** : déplacer une carte vers « Terminé » ferme
l'issue dans Gitea, la ressortir la rouvre (`KANBANTE_SYNC_GITEA=0` pour
désactiver). L'état local est réconcilié à chaque chargement de board
(fermées → Terminé, supprimées → purgées).
### Importants corrigés
- Classification des projets : fenêtre d'activité glissante configurable
(`KANBANTE_ACTIVE_WINDOW_DAYS`, défaut 365) et vrai drapeau `archived`
de Gitea — fini l'année codée en dur et l'onglet « Archivés » mensonger.
- Pagination complète des appels Gitea (le plafond serveur de 50 réponses
par page ne tronque plus les dépôts ni les issues, en silence).
- `get_board_state` ne plante plus sur une colonne inconnue ; migration
automatique des bases 0.1.0 (colonne `position`, `notes.updated_at`,
nettoyage des lignes invalides).
- Gitea injoignable → page d'erreur 502 propre (JSON pour l'API) au lieu
d'un 500 brut ; `/api/readiness` teste réellement SQLite et Gitea,
`/api/health` reste un liveness sans dépendance.
- Dockerfile : installation après copie du code (le package installé
n'est plus vide), utilisateur non-root, `HEALTHCHECK`, `.dockerignore`.
### Ajouts
- **Ordre des cartes persisté** dans chaque colonne (aller-retour
glisser-déposer → rechargement).
- **Création d'issues** depuis le board (`POST /api/issues`).
- **Vue Focus** (`/focus`) : tout ce qui est En cours / En révision,
tous projets actifs confondus.
- Filtres par texte et par étiquette sur le board ; les cartes lient
vers l'issue Gitea ; les pull requests ne sont plus affichées comme
des issues.
- Suite de tests `pytest` (modèles, client Gitea, API, auth/CSRF) et
CI Gitea Actions (`.gitea/workflows/ci.yml`).
- Fichier `LICENSE` (MIT, annoncé par le README depuis la 0.1.0).
### Détails
- Client Gitea entièrement asynchrone (les routes ne bloquent plus la
boucle d'événements), cache mémoire court des listes, en-tête
`Authorization` seulement si un jeton est configuré, uid résolu via
`/user` (plus de `uid=1` ni d'utilisateur codés en dur), `.env` chargé
depuis la racine du projet seulement.
- Bibliothèques JS (HTMX, Alpine, SortableJS) **vendorées** dans
`static/vendor/` : plus aucune dépendance CDN à l'exécution.
- Glisser-déposer : en cas d'échec serveur, la carte est replacée et le
toast d'erreur est rouge ; les déplacements envoient l'ordre complet
des colonnes source et destination.
- API : codes HTTP corrects (400 colonne invalide, 403 CSRF, 413 note
trop longue — limite configurable), `lifespan` FastAPI à la place de
`on_event` déprécié, imports nettoyés.
- CSS : fond des badges corrigé (`color-mix()` remplace l'invalide
`var(--accent)20`).
- Recherche du dashboard : le nom des dépôts passe par un attribut
`data-search` échappé, plus aucune interpolation dans du JS.
- `docker-compose.yml` : clé `version:` obsolète retirée, variables
d'auth exposées, healthcheck.
## 0.1.0 — 2026-07-07
Version initiale : dashboard des projets Gitea, board Kanban 5 colonnes
par dépôt (glisser-déposer SortableJS), notes par projet, état local
SQLite, thème sombre, Dockerfile + docker-compose.