Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
"""Prioritization Engine — generates actionable suggestions based on task state."""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
from sqlalchemy.orm import Session
|
||||
from app.models import Task
|
||||
|
||||
BERLIN_TZ = ZoneInfo("Europe/Berlin")
|
||||
|
||||
|
||||
def generate_suggestions(db: Session) -> list[dict]:
|
||||
"""Analyze open tasks and generate prioritization suggestions.
|
||||
|
||||
Returns a list of suggestion dicts with: id, content, type, severity.
|
||||
"""
|
||||
now = datetime.now(BERLIN_TZ)
|
||||
today = now.date()
|
||||
suggestions = []
|
||||
suggestion_id = 1
|
||||
|
||||
open_tasks = db.query(Task).filter(Task.status == "open").all()
|
||||
|
||||
if not open_tasks:
|
||||
return []
|
||||
|
||||
# --- 1. Overdue tasks ---
|
||||
overdue_tasks = [
|
||||
t for t in open_tasks
|
||||
if t.due_date and t.due_date.date() < today
|
||||
]
|
||||
for t in overdue_tasks[:3]: # Limit to top 3
|
||||
days_overdue = (today - t.due_date.date()).days
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"⚠️ \"{t.title}\" is {days_overdue} day{'s' if days_overdue != 1 else ''} overdue. Reschedule or complete it.",
|
||||
"type": "overdue",
|
||||
"severity": "high",
|
||||
"task_id": t.id,
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 2. Due tomorrow ---
|
||||
tomorrow = today + timedelta(days=1)
|
||||
due_tomorrow = [
|
||||
t for t in open_tasks
|
||||
if t.due_date and t.due_date.date() == tomorrow
|
||||
]
|
||||
for t in due_tomorrow:
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"📅 \"{t.title}\" is due tomorrow.",
|
||||
"type": "upcoming",
|
||||
"severity": "medium",
|
||||
"task_id": t.id,
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 3. Due this week ---
|
||||
week_end = today + timedelta(days=7)
|
||||
due_this_week = [
|
||||
t for t in open_tasks
|
||||
if t.due_date and today < t.due_date.date() <= week_end
|
||||
and t.due_date.date() != tomorrow # Already covered above
|
||||
]
|
||||
if len(due_this_week) > 3:
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"📋 You have {len(due_this_week)} tasks due this week. Plan your time.",
|
||||
"type": "workload",
|
||||
"severity": "medium",
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 4. High-priority tasks without due dates ---
|
||||
high_no_date = [
|
||||
t for t in open_tasks
|
||||
if t.priority and t.priority <= 2 and not t.due_date
|
||||
]
|
||||
for t in high_no_date[:2]: # Limit to top 2
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"🎯 \"{t.title}\" is high priority but has no deadline. Set a due date.",
|
||||
"type": "missing_date",
|
||||
"severity": "medium",
|
||||
"task_id": t.id,
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 5. Tasks idle for 7+ days ---
|
||||
idle_threshold = now - timedelta(days=7)
|
||||
idle_tasks = [
|
||||
t for t in open_tasks
|
||||
if t.created_at and t.created_at < idle_threshold
|
||||
and (not t.due_date) # Only flag idle tasks without deadlines
|
||||
and t.priority and t.priority >= 3 # Low/medium priority
|
||||
]
|
||||
if len(idle_tasks) > 5:
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"🧹 {len(idle_tasks)} low-priority tasks have been sitting for over a week. Review and clean up.",
|
||||
"type": "stale",
|
||||
"severity": "low",
|
||||
})
|
||||
suggestion_id += 1
|
||||
elif idle_tasks:
|
||||
oldest = max(idle_tasks, key=lambda t: (now - t.created_at).days if t.created_at else 0)
|
||||
if oldest.created_at:
|
||||
days_idle = (now - oldest.created_at).days
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"🧹 \"{oldest.title}\" has been open for {days_idle} days. Still relevant?",
|
||||
"type": "stale",
|
||||
"severity": "low",
|
||||
"task_id": oldest.id,
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 6. Too many high-priority tasks ---
|
||||
high_priority_count = len([t for t in open_tasks if t.priority and t.priority <= 2])
|
||||
if high_priority_count > 5:
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": f"🔥 You have {high_priority_count} high-priority tasks. If everything is urgent, nothing is. Consider demoting some.",
|
||||
"type": "overload",
|
||||
"severity": "medium",
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
# --- 7. No tasks due soon (might need planning) ---
|
||||
tasks_with_dates = [t for t in open_tasks if t.due_date]
|
||||
if len(open_tasks) > 10 and len(tasks_with_dates) < 3:
|
||||
suggestions.append({
|
||||
"id": suggestion_id,
|
||||
"content": "📆 Most of your tasks have no due dates. Consider scheduling your top priorities.",
|
||||
"type": "planning",
|
||||
"severity": "low",
|
||||
})
|
||||
suggestion_id += 1
|
||||
|
||||
return suggestions
|
||||
Reference in New Issue
Block a user