"""Weekly coding recap generator - ISO weeks, Gitea repos, brain excluded""" import os, subprocess, datetime, json from pathlib import Path TOKEN_FILE = Path.home() / ".git-credentials" TMPBASE = Path("/tmp/gitea_recap") BRAIN_RECAP_DIR = Path.home() / "brain" / "areas" / "coding" / "recaps" # Repos to track - code only, no brain REPOS = [ "tactility","tactility_apps","mcp_screen","reyna-cli","mac_mcp", "eink-dairy","eink-api","emulatedisplay","basic1", "EMI-Backend","EMI-web","EMI-ExpoAPP","immich-emi", "pico-8","whisper-translation","eink_api","mcp_screen" ] # Deduplicate preserve order REPOS = list(dict.fromkeys(REPOS)) def get_token(): try: cred = TOKEN_FILE.read_text() # format https://user:token@host part = cred.split("://",1)[1] token = part.split(":")[1].split("@")[0] return token.strip() except Exception as e: print(f"no token: {e}") return None def ensure_clones(token): TMPBASE.mkdir(exist_ok=True) for repo in REPOS: dest = TMPBASE / repo url = f"https://adolforeyna:{token}@git.reynafamily.com/adolforeyna/{repo}.git" if not dest.exists(): print(f"cloning {repo}") subprocess.run(["git","clone","--quiet",url,str(dest)], capture_output=True, timeout=120) else: subprocess.run(["git","-C",str(dest),"fetch","--all","--quiet"], capture_output=True, timeout=60) def get_commits_for_week(repo, since, until): dest = TMPBASE / repo if not dest.exists(): return [] cmd = ["git","-C",str(dest),"log","--all", "--since",since,"--until",until, "--pretty=format:%h|%ad|%an|%s","--date=short"] r = subprocess.run(cmd, capture_output=True, text=True, timeout=15) if r.returncode!=0 or not r.stdout.strip(): return [] commits=[] for line in r.stdout.strip().split("\n"): if not line.strip(): continue if "daily auto-sync" in line.lower(): continue parts=line.split("|",3) if len(parts)<4: continue sha, date, author, msg = parts # extra filter noise if msg.lower().startswith("merge") and "auto-sync" in msg.lower(): continue commits.append({"sha":sha,"date":date,"author":author,"msg":msg}) return commits def generate_markdown(week_label, date_range, commits_by_repo, total): since, until = date_range front = f"""--- Date: {since} to {until} Author: Hermes Tags: [coding-recap, weekly, iso-{week_label}] Week: {week_label} Commits: {total} ActiveRepos: {len([k for k,v in commits_by_repo.items() if v])} --- # Weekly Coding Recap - {week_label} ({since} to {until}) ## Summary - **Total commits:** {total} coding commits (brain excluded, noise filtered) - **Active repos:** {len([k for k,v in commits_by_repo.items() if v])} - **Repos:** {', '.join([f"{k} ({len(v)})" for k,v in commits_by_repo.items() if v]) or 'none'} """ if total==0: front += """## Highlights by Repo - No code pushes this week. ## Themes - Break / docs / planning week or local-only work not yet pushed. ## Metrics - 0 commits pushed to Gitea code repos. """ return front body = "## Highlights by Repo\n\n" for repo, commits in commits_by_repo.items(): if not commits: continue body += f"### {repo} ({len(commits)} commits)\n" for c in commits[:12]: body += f"- {c['sha']} {c['date']} {c['msg'][:120]}\n" if len(commits)>12: body += f"- ... and {len(commits)-12} more\n" body += "\n" # simple theme detection keywords = [] all_msgs = " ".join([c['msg'] for commits in commits_by_repo.values() for c in commits]).lower() if "mp3" in all_msgs: keywords.append("Mp3Player/app work") if "audio" in all_msgs: keywords.append("audio pipeline") if "mcp" in all_msgs or "websocket" in all_msgs: keywords.append("MCP/voice") if "tactility" in all_msgs or "i2c" in all_msgs: keywords.append("Tactility drivers") if "reyna-cli" in all_msgs: keywords.append("CLI tooling") theme = ", ".join(keywords) if keywords else "general maintenance" body += f"## Themes\n- Focus: {theme}\n\n" body += f"## Metrics\n- {total} commits across {len([k for k,v in commits_by_repo.items() if v])} repos\n\n" return front + body def main(): token = get_token() if not token: print("Cannot get token") return ensure_clones(token) # Determine previous ISO week (Mon-Sun) for cron today = datetime.date.today() # If called with --week override import sys if "--week-start" in sys.argv: idx = sys.argv.index("--week-start") start_str = sys.argv[idx+1] start = datetime.date.fromisoformat(start_str) end = start + datetime.timedelta(days=6) else: # previous week Mon-Sun # today is Monday? For cron Monday 8am we want last week # last Monday last_monday = today - datetime.timedelta(days=today.weekday()+7) start = last_monday end = start + datetime.timedelta(days=6) since = start.isoformat() until = end.isoformat() iso_year, iso_week, _ = start.isocalendar() week_label = f"{iso_year}-W{iso_week:02d}" print(f"Generating recap for {week_label} {since} to {until}") commits_by_repo = {} total=0 for repo in REPOS: commits = get_commits_for_week(repo, since, until+" 23:59:59") if commits: commits_by_repo[repo]=commits total+=len(commits) else: commits_by_repo[repo]=[] md = generate_markdown(week_label, (since, until), {k:v for k,v in commits_by_repo.items() if v}, total) BRAIN_RECAP_DIR.mkdir(parents=True, exist_ok=True) out = BRAIN_RECAP_DIR / f"{week_label}.md" out.write_text(md) print(f"Wrote {out} ({total} commits)") # update index index_path = Path.home() / "brain" / "areas" / "coding.md" if index_path.exists(): text = index_path.read_text() # ensure entry exists - simple append logic handled by cron? just log print(f"Index exists, please verify W{week_label} listed") # git add? brain auto-sync will handle print(md[:2000]) if __name__=="__main__": main()