Add weekly review - review.py: Aggregates stats from all tools - 35 tools!
This commit is contained in:
@ -29,6 +29,11 @@
|
||||
"value": 34.0,
|
||||
"timestamp": "2026-01-30T23:58:58.553542",
|
||||
"note": "Last before midnight!"
|
||||
},
|
||||
{
|
||||
"value": 35.0,
|
||||
"timestamp": "2026-01-30T23:59:42.953413",
|
||||
"note": null
|
||||
}
|
||||
],
|
||||
"created": "2026-01-30T23:54:10.266015"
|
||||
|
||||
128
tools/review.py
Executable file
128
tools/review.py
Executable file
@ -0,0 +1,128 @@
|
||||
#!/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()
|
||||
1
ws
1
ws
@ -50,6 +50,7 @@ COMMANDS = {
|
||||
'gen': ('tools/gen.py', 'Password, UUID, lorem, etc.'),
|
||||
'fortune': ('tools/fortune.py', 'Random wisdom'),
|
||||
'streak': ('tools/streak.py', 'View all streaks'),
|
||||
'review': ('tools/review.py', 'Weekly/monthly review'),
|
||||
|
||||
# Projects
|
||||
'news': ('projects/news-feed/main.py', 'RSS news reader'),
|
||||
|
||||
Reference in New Issue
Block a user