129 lines
3.9 KiB
Python
Executable File
129 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
review - Weekly and monthly review summaries
|
|
|
|
Aggregate stats and insights across all tools.
|
|
"""
|
|
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from collections import Counter
|
|
|
|
WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
|
|
|
|
def load_json(path: Path):
|
|
if path.exists():
|
|
try:
|
|
with open(path) as f:
|
|
return json.load(f)
|
|
except:
|
|
pass
|
|
return {}
|
|
|
|
def weekly_review():
|
|
"""Generate weekly review."""
|
|
now = datetime.now()
|
|
week_ago = now - timedelta(days=7)
|
|
|
|
print(f"\n📊 Weekly Review")
|
|
print(f" {week_ago.strftime('%b %d')} - {now.strftime('%b %d, %Y')}")
|
|
print("=" * 50)
|
|
|
|
# Time tracked
|
|
time_data = load_json(WORKSPACE / "data" / "timetrack.json")
|
|
entries = [e for e in time_data.get('entries', [])
|
|
if datetime.fromisoformat(e['start']) > week_ago]
|
|
total_mins = sum(e['duration_min'] for e in entries)
|
|
|
|
print(f"\n⏱️ Time Tracked: {total_mins:.0f} minutes ({total_mins/60:.1f} hours)")
|
|
|
|
# By project
|
|
by_project = Counter()
|
|
for e in entries:
|
|
by_project[e.get('project') or 'general'] += e['duration_min']
|
|
|
|
if by_project:
|
|
print(" By project:")
|
|
for proj, mins in by_project.most_common(5):
|
|
print(f" {proj}: {mins:.0f}m")
|
|
|
|
# Habits
|
|
habits_data = load_json(WORKSPACE / "data" / "habits.json")
|
|
habits = habits_data.get('habits', {})
|
|
log = habits_data.get('log', {})
|
|
|
|
habit_completion = {}
|
|
for habit_name in habits:
|
|
if not habits[habit_name].get('active', True):
|
|
continue
|
|
done = 0
|
|
for i in range(7):
|
|
date = (now - timedelta(days=i)).strftime("%Y-%m-%d")
|
|
if habit_name in log.get(date, []):
|
|
done += 1
|
|
habit_completion[habit_name] = done
|
|
|
|
if habit_completion:
|
|
print(f"\n✅ Habits (days completed / 7):")
|
|
for habit, done in sorted(habit_completion.items(), key=lambda x: -x[1]):
|
|
bar = "█" * done + "░" * (7 - done)
|
|
print(f" {habit}: [{bar}] {done}/7")
|
|
|
|
# Goals progress
|
|
goals_data = load_json(WORKSPACE / "data" / "goals.json")
|
|
goals = goals_data.get('goals', [])
|
|
active_goals = [g for g in goals if g['status'] == 'active']
|
|
|
|
if active_goals:
|
|
print(f"\n🎯 Goals:")
|
|
for goal in active_goals:
|
|
print(f" {goal['title'][:30]}: {goal['progress']}%")
|
|
|
|
# Captures/ideas added
|
|
captures = load_json(WORKSPACE / "inbox" / "captures.json")
|
|
if isinstance(captures, list):
|
|
recent = [c for c in captures
|
|
if datetime.fromisoformat(c['captured']) > week_ago]
|
|
if recent:
|
|
print(f"\n📥 Captured: {len(recent)} items")
|
|
|
|
ideas_data = load_json(WORKSPACE / "data" / "ideas.json")
|
|
if isinstance(ideas_data, list):
|
|
recent_ideas = [i for i in ideas_data
|
|
if datetime.fromisoformat(i['created']) > week_ago]
|
|
if recent_ideas:
|
|
print(f"💡 New Ideas: {len(recent_ideas)}")
|
|
|
|
# Notes
|
|
notes_count = 0
|
|
for i in range(7):
|
|
date = (now - timedelta(days=i)).strftime("%Y-%m-%d")
|
|
path = WORKSPACE / "memory" / f"{date}.md"
|
|
if path.exists():
|
|
notes_count += 1
|
|
|
|
print(f"\n📝 Days with notes: {notes_count}/7")
|
|
|
|
# Gratitude
|
|
gratitude = load_json(WORKSPACE / "data" / "gratitude.json")
|
|
if isinstance(gratitude, list):
|
|
recent = [g for g in gratitude
|
|
if datetime.fromisoformat(g['date']) > week_ago]
|
|
if recent:
|
|
print(f"🙏 Gratitude entries: {len(recent)}")
|
|
|
|
print("\n" + "=" * 50)
|
|
print()
|
|
|
|
def main():
|
|
import sys
|
|
|
|
if len(sys.argv) > 1 and sys.argv[1] == 'monthly':
|
|
print("Monthly review coming soon...")
|
|
else:
|
|
weekly_review()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|