Files
kanbante/CHANGELOG.md
T

20 KiB
Raw Blame History

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.