#!/usr/bin/env python3 """ standup - Generate daily standup notes Pulls from yesterday's notes, today's tasks, and active work. """ import json from datetime import datetime, timedelta from pathlib import Path WORKSPACE = Path("/home/wdjones/.openclaw/workspace") def load_json(path: Path): """Load JSON file safely.""" if path.exists(): try: with open(path) as f: return json.load(f) except: pass return {} if 'json' in str(path) else [] def get_yesterday_notes(): """Get yesterday's activity from memory.""" yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d") notes_file = WORKSPACE / "memory" / f"{yesterday}.md" if not notes_file.exists(): return None return notes_file.read_text() def get_tasks(): """Get current tasks.""" tasks_file = WORKSPACE / "TASKS.md" if not tasks_file.exists(): return {'in_progress': [], 'waiting': []} result = {'in_progress': [], 'waiting': []} section = None with open(tasks_file) as f: for line in f: if "## In Progress" in line: section = 'in_progress' elif "## Waiting" in line: section = 'waiting' elif "## Done" in line or "## Inbox" in line: section = None elif section and line.strip().startswith("- [ ]"): task = line.strip()[6:].strip() result[section].append(task) return result def get_time_tracked(): """Get yesterday's time tracking.""" data = load_json(WORKSPACE / "data" / "timetrack.json") yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d") entries = [e for e in data.get('entries', []) if e['start'].startswith(yesterday)] if not entries: return None total_mins = sum(e['duration_min'] for e in entries) by_project = {} for e in entries: proj = e.get('project') or 'general' by_project[proj] = by_project.get(proj, 0) + e['duration_min'] return {'total_mins': total_mins, 'by_project': by_project} def get_blockers(): """Get waiting/blocked items as potential blockers.""" tasks = get_tasks() return tasks.get('waiting', []) def format_duration(mins: float) -> str: if mins < 60: return f"{mins:.0f}m" hours = int(mins // 60) m = int(mins % 60) return f"{hours}h {m}m" def generate_standup(): """Generate standup notes.""" now = datetime.now() print(f"\n📋 Daily Standup - {now.strftime('%A, %B %d, %Y')}") print("=" * 50) # Yesterday print("\n**Yesterday:**") time_data = get_time_tracked() if time_data: print(f" • Tracked {format_duration(time_data['total_mins'])} of work") for proj, mins in time_data['by_project'].items(): print(f" - {proj}: {format_duration(mins)}") else: print(" • (no time tracked)") # Today print("\n**Today:**") tasks = get_tasks() if tasks['in_progress']: for task in tasks['in_progress'][:5]: print(f" • {task[:50]}") else: print(" • (no tasks in progress)") # Blockers print("\n**Blockers:**") blockers = get_blockers() if blockers: for blocker in blockers[:3]: print(f" ⚠️ {blocker[:50]}") else: print(" • None") print("\n" + "=" * 50) print() def main(): generate_standup() if __name__ == "__main__": main()