diff --git a/dev_session.py b/dev_session.py index 751449c0..852fcdba 100644 --- a/dev_session.py +++ b/dev_session.py @@ -469,15 +469,11 @@ def generate_git_summary() -> Tuple[str, str]: except subprocess.CalledProcessError: main_branch = "HEAD~1" # Fallback, falls gar kein Branch gefunden wird - # Git diff --stat - diff_stat_cmd = ["git", "diff", "--stat", f"{main_branch}...HEAD"] - diff_stat = subprocess.check_output(diff_stat_cmd).decode("utf-8").strip() - # Git log --pretty commit_log_cmd = ["git", "log", "--pretty=format:- %s", f"{main_branch}...HEAD"] commit_messages = subprocess.check_output(commit_log_cmd).decode("utf-8").strip() - return diff_stat, commit_messages + return "", commit_messages except subprocess.CalledProcessError as e: print(f"❌ FEHLER beim Generieren der Git-Zusammenfassung: {e}") return "", "" @@ -520,7 +516,7 @@ def report_status_to_notion( summary_override: Optional[str] ) -> None: """ - Erstellt einen Statusbericht für den Notion-Task, entweder interaktiv oder mit überschriebenen Werten. + Erstellt einen automatisierten Statusbericht für den Notion-Task basierend auf Git-Commits. """ if not os.path.exists(SESSION_FILE_PATH): print("❌ FEHLER: Keine aktive Session gefunden. Kann keinen Statusbericht erstellen.") @@ -531,6 +527,7 @@ def report_status_to_notion( session_data = json.load(f) task_id = session_data.get("task_id") token = session_data.get("token") + readme_path = session_data.get("readme_path", "readme.md") # Lade den Readme-Pfad if not (task_id and token): print("❌ FEHLER: Session-Daten unvollständig. Kann keinen Statusbericht erstellen.") @@ -542,16 +539,9 @@ def report_status_to_notion( session_start_time = datetime.fromisoformat(session_start_time_str) elapsed_time = datetime.now() - session_start_time elapsed_hours = elapsed_time.total_seconds() / 3600 - - # Get current task page to read existing duration - # Note: This is a simplified way. A more robust solution might query the DB - # to get the page object without a separate API call if we already have it. - # For now, a direct API call is clear and ensures we have the latest data. + task_page_url = f"https://api.notion.com/v1/pages/{task_id}" - headers = { - "Authorization": f"Bearer {token}", - "Notion-Version": "2022-06-28" - } + headers = {"Authorization": f"Bearer {token}", "Notion-Version": "2022-06-28"} try: page_response = requests.get(task_page_url, headers=headers) page_response.raise_for_status() @@ -560,157 +550,83 @@ def report_status_to_notion( current_duration = get_page_number_property(task_page, "Total Duration (h)") or 0.0 new_total_duration = current_duration + elapsed_hours - duration_payload = { - "Total Duration (h)": { - "number": new_total_duration - } - } + duration_payload = {"Total Duration (h)": {"number": new_total_duration}} update_notion_task_property(token, task_id, duration_payload) print(f"✅ Zeiterfassung: {elapsed_hours:.2f} Stunden zum Task hinzugefügt. Neue Gesamtdauer: {new_total_duration:.2f} Stunden.") # Reset session start time for the next interval - save_session_info(task_id, token) + save_session_info(task_id, token, readme_path) except requests.exceptions.RequestException as e: print(f"❌ FEHLER beim Abrufen der Task-Details für die Zeiterfassung: {e}") - print(f"--- Erstelle Statusbericht für Task {task_id} ---") + print(f"--- Erstelle automatischen Statusbericht für Task {task_id} ---") - # Git-Zusammenfassung generieren (immer, wenn nicht explizit überschrieben) - actual_git_changes = git_changes_override - actual_commit_messages = commit_messages_override - if not git_changes_override or not commit_messages_override: - print("Generiere Git-Zusammenfassung...") - diff_stat, commit_log = generate_git_summary() - if not git_changes_override: - actual_git_changes = diff_stat - if not commit_messages_override: - actual_commit_messages = commit_log - - # Status abfragen oder übernehmen - actual_status = status_override - if not actual_status: - tasks_db_id = find_database_by_title(token, "Tasks [UT]") - if tasks_db_id: - status_options = get_database_status_options(token, tasks_db_id) - if status_options: - print("\nBitte wähle den neuen Status des Tasks:") - for i, option in enumerate(status_options): - print(f"[{i+1}] {option}") - while True: - try: - choice = int(input("Wähle eine Nummer: ")) - if 1 <= choice <= len(status_options): - actual_status = status_options[choice - 1] - break - else: - print("Ungültige Auswahl.") - except ValueError: - print("Ungültige Eingabe. Bitte eine Zahl eingeben.") - else: - print("❌ FEHLER: Konnte Status-Optionen nicht abrufen. Abbruch des Berichts.") - return + # Git-Zusammenfassung generieren + print("Generiere Git-Zusammenfassung...") + _, commit_log = generate_git_summary() + actual_commit_messages = commit_log - if not actual_status: - print("❌ FEHLER: Kein Status festgelegt. Abbruch des Berichts.") - return - - # Detaillierte Zusammenfassung abfragen oder übernehmen - actual_summary = summary_override - if not actual_summary: - print("\nBitte gib eine Zusammenfassung der Arbeit ein (was wurde getan, Ergebnisse, Probleme etc.).") - user_summary_lines = [] - while True: - line = input() - if not line: - break - user_summary_lines.append(line) - actual_summary = "\n".join(user_summary_lines) - - # To-Dos abfragen oder übernehmen - actual_todos = todos_override - if not actual_todos: - user_todos = input("\nGibt es offene To-Dos oder nächste Schritte? (Leer lassen zum Überspringen): ") - actual_todos = user_todos.strip() + # Summary automatisch aus Commit-Nachrichten erstellen + actual_summary = summary_override or "Keine Zusammenfassung angegeben." + if not summary_override: + _, commit_log = generate_git_summary() + summary_from_commits = commit_log.replace("- ", "✦ ").strip() + if summary_from_commits: + actual_summary = summary_from_commits + else: + actual_summary = "Keine neuen Commits in dieser Session." # Kommentar zusammenstellen report_lines = [] - # Diese Zeilen werden jetzt innerhalb des Code-Blocks formatiert - - # Add invested time to the report if available if 'elapsed_hours' in locals(): elapsed_hhmm = decimal_hours_to_hhmm(elapsed_hours) report_lines.append(f"Investierte Zeit in dieser Session: {elapsed_hhmm}") - report_lines.append(f"Neuer Status: {actual_status}") - - if actual_summary: - report_lines.append("\nArbeitszusammenfassung:") - report_lines.append(actual_summary) + report_lines.append("\nArbeitszusammenfassung:") + report_lines.append(actual_summary) - if actual_git_changes or actual_commit_messages: - report_lines.append("\nTechnische Änderungen (Git):") - if actual_git_changes: - report_lines.append(f"```{actual_git_changes}```") - if actual_commit_messages: - report_lines.append("\nCommit Nachrichten:") - report_lines.append(f"```{actual_commit_messages}```") - - if actual_todos: - report_lines.append("\nOffene To-Dos / Nächste Schritte:") - for todo_item in actual_todos.split('\n'): - report_lines.append(f"- {todo_item.strip()}") - report_content = "\n".join(report_lines) # Notion Blöcke für die API erstellen timestamp = datetime.now(BERLIN_TZ).strftime('%Y-%m-%d %H:%M') notion_blocks = [ - { - "object": "block", - "type": "heading_2", - "heading_2": { - "rich_text": [{"type": "text", "text": {"content": f"🤖 Status-Update ({timestamp} Berlin Time)"}}] - } - }, - { - "object": "block", - "type": "code", - "code": { - "rich_text": [{"type": "text", "text": {"content": report_content}}], - "language": "yaml" - } - } + {"object": "block", "type": "heading_2", "heading_2": {"rich_text": [{"type": "text", "text": {"content": f"🤖 Status-Update ({timestamp} Berlin Time)"}}]}}, + {"object": "block", "type": "code", "code": {"rich_text": [{"type": "text", "text": {"content": report_content}}], "language": "yaml"}} ] - # Notion aktualisieren + # Notion aktualisieren (nur Kommentar/Block, kein Status) append_blocks_to_notion_page(token, task_id, notion_blocks) - status_payload = {"Status": {"status": {"name": actual_status}}} - update_notion_task_property(token, task_id, status_payload) - # --- Git Operationen --- + # --- Doku & Git Operationen --- print("\n--- Führe Git-Operationen aus ---") try: + # Doku-Update-Logik (vor dem Staging) + git_status_output_doku = subprocess.run(["git", "status", "--porcelain", readme_path], capture_output=True, text=True).stdout.strip() + if git_status_output_doku: + print(f"Relevante Dokumentation '{readme_path}' wurde geändert. Committe Änderungen...") + # In einer echten Implementierung könnte hier eine KI-Zusammenfassung stehen. + # Vorerst wird nur die vorhandene Änderung committet. + subprocess.run(["git", "add", readme_path], check=True) + doku_commit_msg = f"Docs: Aktualisierung der Dokumentation für Task [{task_id.split('-')[0]}]" + subprocess.run(["git", "commit", "-m", doku_commit_msg], check=True) + print("✅ Dokumentation committet.") + + # Stage alle anderen Änderungen subprocess.run(["git", "add", "."], check=True) - print("✅ Alle Änderungen gestaged (git add .).") - # Prüfen, ob es Änderungen zum Committen gibt - git_status_output = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=True).stdout.strip() - if not git_status_output: - print("⚠️ Keine Änderungen zum Committen gefunden. Überspringe git commit.") - return # Beende die Funktion, da nichts zu tun ist + git_status_output_rest = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=True).stdout.strip() + if git_status_output_rest: + # Commit-Nachricht erstellen + commit_subject = actual_summary.splitlines()[0] if actual_summary else "Notion Status Update" + commit_message = f"[{task_id.split('-')[0]}] {commit_subject}\n\n{actual_summary}" + subprocess.run(["git", "commit", "-m", commit_message], check=True) + print("✅ Code-Änderungen committet.") + else: + print("⚠️ Keine weiteren Code-Änderungen zum Committen gefunden.") - # Commit-Nachricht erstellen - commit_subject = actual_summary.splitlines()[0] if actual_summary else "Notion Status Update" - commit_message = f"[{task_id.split('-')[0]}] {commit_subject}\n\n{actual_summary}" - - subprocess.run(["git", "commit", "-m", commit_message], check=True) - print("✅ Git commit erfolgreich.") - - # Interaktive Abfrage für git push - push_choice = input("\n✅ Commit erfolgreich erstellt. Sollen die Änderungen jetzt gepusht werden? (j/n): ").lower() - if push_choice == 'j': - git_push_with_retry() + # Änderungen automatisch pushen + git_push_with_retry() except subprocess.CalledProcessError as e: print(f"❌ FEHLER bei Git-Operationen: {e}") @@ -759,12 +675,13 @@ def generate_cli_context(project_title: str, task_title: str, task_id: str, read # Die start_gemini_cli Funktion wird entfernt, da das aufrufende Skript jetzt die Gemini CLI startet. -def save_session_info(task_id: str, token: str): - """Speichert die Task-ID, den Token und den Startzeitpunkt für den Git-Hook.""" +def save_session_info(task_id: str, token: str, readme_path: Optional[str]): + """Speichert die Task-ID, den Token, den Readme-Pfad und den Startzeitpunkt.""" os.makedirs(SESSION_DIR, exist_ok=True) session_data = { "task_id": task_id, "token": token, + "readme_path": readme_path, "session_start_time": datetime.now().isoformat() } with open(SESSION_FILE_PATH, "w") as f: @@ -867,7 +784,7 @@ def start_interactive_session(): print(f"> Bisher für diesen Task erfasst: {total_duration_hhmm} Stunden.") # Session-Informationen für den Git-Hook speichern - save_session_info(task_id, token) + save_session_info(task_id, token, readme_path) # Git-Hook installieren, der die Session-Infos nutzt install_git_hook()