diff --git a/app/briefing.py b/app/briefing.py index 6adafd5..27b04af 100644 --- a/app/briefing.py +++ b/app/briefing.py @@ -16,6 +16,43 @@ def ntfy_configured(settings: Settings) -> bool: return bool(settings.ntfy_url and settings.ntfy_topic) +def format_standup_text(data: dict) -> str: + """Automatic standup (issue #6): yesterday / today / blockers.""" + lines = [f"🗣️ Standup — {data['today_label']}"] + closed = data["closed_yesterday"] + lines.append( + f"\n✅ Hier ({data['yesterday_label']}) : {len(closed)} fermée(s), " + f"{data['moved_yesterday']} déplacement(s)" + ) + for item in closed[:8]: + lines.append( + f" • {item['repo']} #{item['number']} « {item['title']} »" + ) + lines.append("\n📌 Aujourd'hui :") + if data["picks"]: + for pick in data["picks"]: + lines.append( + f" • {pick['repo']} #{pick['number']} « {pick['title']} »" + f" — {pick['column_label']}" + ) + elif data["focus_titles"]: + for title in data["focus_titles"][:5]: + lines.append(f" • {title}") + lines.append(" (aucun focus épinglé — pense à /today)") + else: + lines.append(" • Rien en cours. Journée libre ou triage à faire !") + lines.append("\n🚧 Blocages :") + if data["blockers"]: + for card in data["blockers"][:6]: + lines.append( + f" • {card['repo']} #{card['number']} « {card['title']} »" + f" — {card['days']} j en {card['column_label']}" + ) + else: + lines.append(" • Aucun blocage signalé. ✨") + return "\n".join(lines) + + def format_briefing_text(data: dict) -> str: """Plain-text briefing (ntfy body, also shown on /briefing).""" lines: list[str] = [f"📋 Kanbante — briefing du {data['date']}"] @@ -67,6 +104,8 @@ def format_briefing_text(data: dict) -> str: if data["focus_total"] == 0 and not data["aging"]: lines.append("\n🎉 Rien d'urgent : aucun encours, aucune carte vieillissante.") + if data.get("standup"): + lines.append("\n" + data["standup"]) return "\n".join(lines) diff --git a/app/config.py b/app/config.py index 933c21a..719d56f 100644 --- a/app/config.py +++ b/app/config.py @@ -68,6 +68,16 @@ Environment variables: KANBANTE_OBSIGATE_MCP_ARGS JSON argument template for the tool; "{title}" and "{content}" placeholders are substituted (JSON-escaped). + KANBANTE_BRIEFING_INCLUDE_STANDUP + "1" appends the automatic standup + (issue #6) to the morning briefing. + KANBANTE_RULES Automation rules (issue #8) as a JSON + array: [{"name": ..., "when": + {"column": "review", "min_age_days": 3}, + "then": {"notify": true}}]. Conditions: + column, min_age_days, label, wip_over. + Actions: add_label, notify, move_top. + A rule can never close an issue. """ import os @@ -76,7 +86,7 @@ from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent -APP_VERSION = "0.12.0" +APP_VERSION = "0.13.0" def _env_bool(name: str, default: bool) -> bool: @@ -142,6 +152,8 @@ class Settings: obsigate_mcp_token: str = "" obsigate_mcp_tool: str = "" obsigate_mcp_args: str = '{"title": "{title}", "content": "{content}"}' + briefing_include_standup: bool = False + rules_raw: str = "" @property def auth_enabled(self) -> bool: @@ -184,4 +196,6 @@ def get_settings() -> Settings: "KANBANTE_OBSIGATE_MCP_ARGS", '{"title": "{title}", "content": "{content}"}', ), + briefing_include_standup=_env_bool("KANBANTE_BRIEFING_INCLUDE_STANDUP", False), + rules_raw=os.getenv("KANBANTE_RULES", ""), ) diff --git a/app/templates/activity.html b/app/templates/activity.html index 8b296ef..844ca5f 100644 --- a/app/templates/activity.html +++ b/app/templates/activity.html @@ -20,10 +20,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/briefing.html b/app/templates/briefing.html index 76596c9..6d04274 100644 --- a/app/templates/briefing.html +++ b/app/templates/briefing.html @@ -24,6 +24,7 @@ ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/capture.html b/app/templates/capture.html index 2462122..ecb9f54 100644 --- a/app/templates/capture.html +++ b/app/templates/capture.html @@ -17,10 +17,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 68f1162..fd8f73b 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -20,10 +20,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/digest.html b/app/templates/digest.html index 618081f..c724c74 100644 --- a/app/templates/digest.html +++ b/app/templates/digest.html @@ -17,6 +17,7 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest diff --git a/app/templates/focus.html b/app/templates/focus.html index 4aebec2..dd17d52 100644 --- a/app/templates/focus.html +++ b/app/templates/focus.html @@ -19,10 +19,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard {{ groups|map(attribute='cards')|map('length')|sum }} cartes en cours diff --git a/app/templates/forecast.html b/app/templates/forecast.html index 3d7b173..7545bc6 100644 --- a/app/templates/forecast.html +++ b/app/templates/forecast.html @@ -17,6 +17,7 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest diff --git a/app/templates/my.html b/app/templates/my.html index c464672..346534c 100644 --- a/app/templates/my.html +++ b/app/templates/my.html @@ -23,6 +23,7 @@ ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/search.html b/app/templates/search.html index 9698b01..3796f4a 100644 --- a/app/templates/search.html +++ b/app/templates/search.html @@ -23,6 +23,7 @@ ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/sprint.html b/app/templates/sprint.html index 7e3332c..87d38bd 100644 --- a/app/templates/sprint.html +++ b/app/templates/sprint.html @@ -16,6 +16,7 @@ 📋 Board 🌅 Aujourd'hui 🔮 Prévisions + ⚙️ Règles diff --git a/app/templates/standup.html b/app/templates/standup.html new file mode 100644 index 0000000..4725668 --- /dev/null +++ b/app/templates/standup.html @@ -0,0 +1,55 @@ + + + + + + + Standup — Kanbante + + + +
+ + +
+ +
+
+

🗣️ Standup automatique

+

Écrit par le journal, pas par la mémoire : fermé/déplacé hier, focus aujourd'hui, cartes qui vieillissent en QA/Révision en blocages.

+

+ + {% if include_in_briefing %} + Inclus dans le briefing ntfy du matin ✔ + {% else %} + Astuce : KANBANTE_BRIEFING_INCLUDE_STANDUP=1 l'ajoute au briefing ntfy du matin. + {% endif %} +

+
+
+
{{ text }}
+
+
+ + {% include "_palette.html" %} + + + + diff --git a/app/templates/today.html b/app/templates/today.html index 08ee5ab..c304d01 100644 --- a/app/templates/today.html +++ b/app/templates/today.html @@ -17,10 +17,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/app/templates/triage.html b/app/templates/triage.html index 54208e0..8182e32 100644 --- a/app/templates/triage.html +++ b/app/templates/triage.html @@ -17,10 +17,12 @@ 👤 Mes issues 📰 Activité 📊 Briefing + 🗣️ Standup 🔍 Recherche ⚡ Capture 🧠 Digest 🔮 Prévisions + ⚙️ Règles 🖥️ Wallboard diff --git a/static/js/palette.js b/static/js/palette.js index cb7cc12..8370613 100644 --- a/static/js/palette.js +++ b/static/js/palette.js @@ -15,6 +15,8 @@ { icon: '🎯', label: 'Focus — en cours, QA, révision', href: '/focus' }, { icon: '🌅', label: "Focus du jour — les 3 cartes d'aujourd'hui", href: '/today' }, { icon: '🔮', label: 'Prévisions — on finit quand ?', href: '/forecast' }, + { icon: '🗣️', label: 'Standup automatique — hier, aujourd\'hui, blocages', href: '/standup' }, + { icon: '⚙️', label: 'Règles d\'automatisation', href: '/rules' }, { icon: '👤', label: 'Mes issues', href: '/my' }, { icon: '📰', label: 'Activité — journal des événements', href: '/activity' }, { icon: '📊', label: 'Briefing quotidien', href: '/briefing' },