diff --git a/.agents/skills/gstack-retro/SKILL.md b/.agents/skills/gstack-retro/SKILL.md index a0b796ba..57685fa4 100644 --- a/.agents/skills/gstack-retro/SKILL.md +++ b/.agents/skills/gstack-retro/SKILL.md @@ -258,6 +258,8 @@ When the user types `/retro`, run this skill. - `/retro 30d` — last 30 days - `/retro compare` — compare current window vs prior same-length window - `/retro compare 14d` — compare with explicit window +- `/retro global` — cross-project retro across all AI coding tools (7d default) +- `/retro global 14d` — cross-project retro with explicit window ## Instructions @@ -265,17 +267,21 @@ Parse the argument to determine the time window. Default to 7 days if no argumen **Midnight-aligned windows:** For day (`d`) and week (`w`) units, compute an absolute start date at local midnight, not a relative string. For example, if today is 2026-03-18 and the window is 7 days: the start date is 2026-03-11. Use `--since="2026-03-11T00:00:00"` for git log queries — the explicit `T00:00:00` suffix ensures git starts from midnight. Without it, git uses the current wall-clock time (e.g., `--since="2026-03-11"` at 11pm means 11pm, not midnight). For week units, multiply by 7 to get days (e.g., `2w` = 14 days back). For hour (`h`) units, use `--since="N hours ago"` since midnight alignment does not apply to sub-day windows. -**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare`, or `compare` followed by a number and `d`/`h`/`w`, show this usage and stop: +**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare` (optionally followed by a window), or the word `global` (optionally followed by a window), show this usage and stop: ``` -Usage: /retro [window] +Usage: /retro [window | compare | global] /retro — last 7 days (default) /retro 24h — last 24 hours /retro 14d — last 14 days /retro 30d — last 30 days /retro compare — compare this period vs prior period /retro compare 14d — compare with explicit window + /retro global — cross-project retro across all AI tools (7d default) + /retro global 14d — cross-project retro with explicit window ``` +**If the first argument is `global`:** Skip the normal repo-scoped retro (Steps 1-14). Instead, follow the **Global Retrospective** flow at the end of this document. The optional second argument is the time window (default 7d). This mode does NOT require being inside a git repo. + ### Step 1: Gather Raw Data First, fetch origin and identify the current user: @@ -721,6 +727,204 @@ Small, practical, realistic. Each must be something that takes <5 minutes to ado --- +## Global Retrospective Mode + +When the user runs `/retro global` (or `/retro global 14d`), follow this flow instead of the repo-scoped Steps 1-14. This mode works from any directory — it does NOT require being inside a git repo. + +### Global Step 1: Compute time window + +Same midnight-aligned logic as the regular retro. Default 7d. The second argument after `global` is the window (e.g., `14d`, `30d`, `24h`). + +### Global Step 2: Run discovery + +Locate and run the discovery script using this fallback chain: + +```bash +DISCOVER_BIN="" +[ -x ~/.codex/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=~/.codex/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && [ -x .agents/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=.agents/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && which gstack-global-discover >/dev/null 2>&1 && DISCOVER_BIN=$(which gstack-global-discover) +[ -z "$DISCOVER_BIN" ] && [ -f bin/gstack-global-discover.ts ] && DISCOVER_BIN="bun run bin/gstack-global-discover.ts" +echo "DISCOVER_BIN: $DISCOVER_BIN" +``` + +If no binary is found, tell the user: "Discovery script not found. Run `bun run build` in the gstack directory to compile it." and stop. + +Run the discovery: +```bash +$DISCOVER_BIN --since "" --format json 2>/tmp/gstack-discover-stderr +``` + +Read the stderr output from `/tmp/gstack-discover-stderr` for diagnostic info. Parse the JSON output from stdout. + +If `total_sessions` is 0, say: "No AI coding sessions found in the last . Try a longer window: `/retro global 30d`" and stop. + +### Global Step 3: Run git log on each discovered repo + +For each repo in the discovery JSON's `repos` array, find the first valid path in `paths[]` (directory exists with `.git/`). If no valid path exists, skip the repo and note it. + +**For local-only repos** (where `remote` starts with `local:`): skip `git fetch` and use the local default branch. Use `git log HEAD` instead of `git log origin/$DEFAULT`. + +**For repos with remotes:** + +```bash +git -C fetch origin --quiet 2>/dev/null +``` + +Detect the default branch for each repo: first try `git symbolic-ref refs/remotes/origin/HEAD`, then check common branch names (`main`, `master`), then fall back to `git rev-parse --abbrev-ref HEAD`. Use the detected branch as `` in the commands below. + +```bash +# Commits with stats +git -C log origin/$DEFAULT --since="T00:00:00" --format="%H|%aN|%ai|%s" --shortstat + +# Commit timestamps for session detection, streak, and context switching +git -C log origin/$DEFAULT --since="T00:00:00" --format="%at|%aN|%ai|%s" | sort -n + +# Per-author commit counts +git -C shortlog origin/$DEFAULT --since="T00:00:00" -sn --no-merges + +# PR numbers from commit messages +git -C log origin/$DEFAULT --since="T00:00:00" --format="%s" | grep -oE '#[0-9]+' | sort -n | uniq +``` + +For repos that fail (deleted paths, network errors): skip and note "N repos could not be reached." + +### Global Step 4: Compute global shipping streak + +For each repo, get commit dates (capped at 365 days): + +```bash +git -C log origin/$DEFAULT --since="365 days ago" --format="%ad" --date=format:"%Y-%m-%d" | sort -u +``` + +Union all dates across all repos. Count backward from today — how many consecutive days have at least one commit to ANY repo? If the streak hits 365 days, display as "365+ days". + +### Global Step 5: Compute context switching metric + +From the commit timestamps gathered in Step 3, group by date. For each date, count how many distinct repos had commits that day. Report: +- Average repos/day +- Maximum repos/day +- Which days were focused (1 repo) vs. fragmented (3+ repos) + +### Global Step 6: Per-tool productivity patterns + +From the discovery JSON, analyze tool usage patterns: +- Which AI tool is used for which repos (exclusive vs. shared) +- Session count per tool +- Behavioral patterns (e.g., "Codex used exclusively for myapp, Claude Code for everything else") + +### Global Step 7: Aggregate and generate narrative + +Structure the output as: + +--- + +**Tweetable summary** (first line, before everything else): +``` +Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d +``` + +## Global Engineering Retro: [date range] + +### Overview +| Metric | Value | +|--------|-------| +| Projects active | N | +| Total commits (all repos) | N | +| Total LOC | +N / -N | +| AI coding sessions | N (CC: X, Codex: Y, Gemini: Z) | +| Active days | N | +| Global shipping streak | N consecutive days | +| Context switches/day | N avg (max: M) | + +### Per-Project Breakdown +For each repo (sorted by commits descending): +- Repo name (with % of total commits) +- Commits, LOC, PRs merged, top contributor +- Key work (inferred from commit messages) +- AI sessions by tool + +### Cross-Project Patterns +- Time allocation across projects (% breakdown) +- Peak productivity hours aggregated across all repos +- Focused vs. fragmented days +- Context switching trends + +### Tool Usage Analysis +Per-tool breakdown with behavioral patterns: +- Claude Code: N sessions across M repos — patterns observed +- Codex: N sessions across M repos — patterns observed +- Gemini: N sessions across M repos — patterns observed + +### Ship of the Week (Global) +Highest-impact PR across ALL projects. Identify by LOC and commit messages. + +### 3 Cross-Project Insights +What the global view reveals that no single-repo retro could show. + +### 3 Habits for Next Week +Considering the full cross-project picture. + +--- + +### Global Step 8: Load history & compare + +```bash +ls -t ~/.gstack/retros/global-*.json 2>/dev/null | head -5 +``` + +**Only compare against a prior retro with the same `window` value** (e.g., 7d vs 7d). If the most recent prior retro has a different window, skip comparison and note: "Prior global retro used a different window — skipping comparison." + +If a matching prior retro exists, load it with the Read tool. Show a **Trends vs Last Global Retro** table with deltas for key metrics: total commits, LOC, sessions, streak, context switches/day. + +If no prior global retros exist, append: "First global retro recorded — run again next week to see trends." + +### Global Step 9: Save snapshot + +```bash +mkdir -p ~/.gstack/retros +``` + +Determine the next sequence number for today: +```bash +today=$(date +%Y-%m-%d) +existing=$(ls ~/.gstack/retros/global-${today}-*.json 2>/dev/null | wc -l | tr -d ' ') +next=$((existing + 1)) +``` + +Use the Write tool to save JSON to `~/.gstack/retros/global-${today}-${next}.json`: + +```json +{ + "type": "global", + "date": "2026-03-21", + "window": "7d", + "projects": [ + { + "name": "gstack", + "remote": "https://github.com/garrytan/gstack", + "commits": 47, + "insertions": 3200, + "deletions": 800, + "sessions": { "claude_code": 15, "codex": 3, "gemini": 0 } + } + ], + "totals": { + "commits": 182, + "insertions": 15300, + "deletions": 4200, + "projects": 5, + "active_days": 6, + "sessions": { "claude_code": 48, "codex": 8, "gemini": 3 }, + "global_streak_days": 52, + "avg_context_switches_per_day": 2.1 + }, + "tweetable": "Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d" +} +``` + +--- + ## Compare Mode When the user runs `/retro compare` (or `/retro compare 14d`): @@ -754,3 +958,4 @@ When the user runs `/retro compare` (or `/retro compare 14d`): - Treat merge commits as PR boundaries - Do not read CLAUDE.md or other docs — this skill is self-contained - On first run (no prior retros), skip comparison sections gracefully +- **Global mode:** Does NOT require being inside a git repo. Saves snapshots to `~/.gstack/retros/` (not `.context/retros/`). Gracefully skip AI tools that aren't installed. Only compare against prior global retros with the same window value. If streak hits 365d cap, display as "365+ days". diff --git a/retro/SKILL.md b/retro/SKILL.md index 635b5747..1c4f108f 100644 --- a/retro/SKILL.md +++ b/retro/SKILL.md @@ -265,6 +265,8 @@ When the user types `/retro`, run this skill. - `/retro 30d` — last 30 days - `/retro compare` — compare current window vs prior same-length window - `/retro compare 14d` — compare with explicit window +- `/retro global` — cross-project retro across all AI coding tools (7d default) +- `/retro global 14d` — cross-project retro with explicit window ## Instructions @@ -272,17 +274,21 @@ Parse the argument to determine the time window. Default to 7 days if no argumen **Midnight-aligned windows:** For day (`d`) and week (`w`) units, compute an absolute start date at local midnight, not a relative string. For example, if today is 2026-03-18 and the window is 7 days: the start date is 2026-03-11. Use `--since="2026-03-11T00:00:00"` for git log queries — the explicit `T00:00:00` suffix ensures git starts from midnight. Without it, git uses the current wall-clock time (e.g., `--since="2026-03-11"` at 11pm means 11pm, not midnight). For week units, multiply by 7 to get days (e.g., `2w` = 14 days back). For hour (`h`) units, use `--since="N hours ago"` since midnight alignment does not apply to sub-day windows. -**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare`, or `compare` followed by a number and `d`/`h`/`w`, show this usage and stop: +**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare` (optionally followed by a window), or the word `global` (optionally followed by a window), show this usage and stop: ``` -Usage: /retro [window] +Usage: /retro [window | compare | global] /retro — last 7 days (default) /retro 24h — last 24 hours /retro 14d — last 14 days /retro 30d — last 30 days /retro compare — compare this period vs prior period /retro compare 14d — compare with explicit window + /retro global — cross-project retro across all AI tools (7d default) + /retro global 14d — cross-project retro with explicit window ``` +**If the first argument is `global`:** Skip the normal repo-scoped retro (Steps 1-14). Instead, follow the **Global Retrospective** flow at the end of this document. The optional second argument is the time window (default 7d). This mode does NOT require being inside a git repo. + ### Step 1: Gather Raw Data First, fetch origin and identify the current user: @@ -728,6 +734,204 @@ Small, practical, realistic. Each must be something that takes <5 minutes to ado --- +## Global Retrospective Mode + +When the user runs `/retro global` (or `/retro global 14d`), follow this flow instead of the repo-scoped Steps 1-14. This mode works from any directory — it does NOT require being inside a git repo. + +### Global Step 1: Compute time window + +Same midnight-aligned logic as the regular retro. Default 7d. The second argument after `global` is the window (e.g., `14d`, `30d`, `24h`). + +### Global Step 2: Run discovery + +Locate and run the discovery script using this fallback chain: + +```bash +DISCOVER_BIN="" +[ -x ~/.claude/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=~/.claude/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && [ -x .claude/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=.claude/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && which gstack-global-discover >/dev/null 2>&1 && DISCOVER_BIN=$(which gstack-global-discover) +[ -z "$DISCOVER_BIN" ] && [ -f bin/gstack-global-discover.ts ] && DISCOVER_BIN="bun run bin/gstack-global-discover.ts" +echo "DISCOVER_BIN: $DISCOVER_BIN" +``` + +If no binary is found, tell the user: "Discovery script not found. Run `bun run build` in the gstack directory to compile it." and stop. + +Run the discovery: +```bash +$DISCOVER_BIN --since "" --format json 2>/tmp/gstack-discover-stderr +``` + +Read the stderr output from `/tmp/gstack-discover-stderr` for diagnostic info. Parse the JSON output from stdout. + +If `total_sessions` is 0, say: "No AI coding sessions found in the last . Try a longer window: `/retro global 30d`" and stop. + +### Global Step 3: Run git log on each discovered repo + +For each repo in the discovery JSON's `repos` array, find the first valid path in `paths[]` (directory exists with `.git/`). If no valid path exists, skip the repo and note it. + +**For local-only repos** (where `remote` starts with `local:`): skip `git fetch` and use the local default branch. Use `git log HEAD` instead of `git log origin/$DEFAULT`. + +**For repos with remotes:** + +```bash +git -C fetch origin --quiet 2>/dev/null +``` + +Detect the default branch for each repo: first try `git symbolic-ref refs/remotes/origin/HEAD`, then check common branch names (`main`, `master`), then fall back to `git rev-parse --abbrev-ref HEAD`. Use the detected branch as `` in the commands below. + +```bash +# Commits with stats +git -C log origin/$DEFAULT --since="T00:00:00" --format="%H|%aN|%ai|%s" --shortstat + +# Commit timestamps for session detection, streak, and context switching +git -C log origin/$DEFAULT --since="T00:00:00" --format="%at|%aN|%ai|%s" | sort -n + +# Per-author commit counts +git -C shortlog origin/$DEFAULT --since="T00:00:00" -sn --no-merges + +# PR numbers from commit messages +git -C log origin/$DEFAULT --since="T00:00:00" --format="%s" | grep -oE '#[0-9]+' | sort -n | uniq +``` + +For repos that fail (deleted paths, network errors): skip and note "N repos could not be reached." + +### Global Step 4: Compute global shipping streak + +For each repo, get commit dates (capped at 365 days): + +```bash +git -C log origin/$DEFAULT --since="365 days ago" --format="%ad" --date=format:"%Y-%m-%d" | sort -u +``` + +Union all dates across all repos. Count backward from today — how many consecutive days have at least one commit to ANY repo? If the streak hits 365 days, display as "365+ days". + +### Global Step 5: Compute context switching metric + +From the commit timestamps gathered in Step 3, group by date. For each date, count how many distinct repos had commits that day. Report: +- Average repos/day +- Maximum repos/day +- Which days were focused (1 repo) vs. fragmented (3+ repos) + +### Global Step 6: Per-tool productivity patterns + +From the discovery JSON, analyze tool usage patterns: +- Which AI tool is used for which repos (exclusive vs. shared) +- Session count per tool +- Behavioral patterns (e.g., "Codex used exclusively for myapp, Claude Code for everything else") + +### Global Step 7: Aggregate and generate narrative + +Structure the output as: + +--- + +**Tweetable summary** (first line, before everything else): +``` +Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d +``` + +## Global Engineering Retro: [date range] + +### Overview +| Metric | Value | +|--------|-------| +| Projects active | N | +| Total commits (all repos) | N | +| Total LOC | +N / -N | +| AI coding sessions | N (CC: X, Codex: Y, Gemini: Z) | +| Active days | N | +| Global shipping streak | N consecutive days | +| Context switches/day | N avg (max: M) | + +### Per-Project Breakdown +For each repo (sorted by commits descending): +- Repo name (with % of total commits) +- Commits, LOC, PRs merged, top contributor +- Key work (inferred from commit messages) +- AI sessions by tool + +### Cross-Project Patterns +- Time allocation across projects (% breakdown) +- Peak productivity hours aggregated across all repos +- Focused vs. fragmented days +- Context switching trends + +### Tool Usage Analysis +Per-tool breakdown with behavioral patterns: +- Claude Code: N sessions across M repos — patterns observed +- Codex: N sessions across M repos — patterns observed +- Gemini: N sessions across M repos — patterns observed + +### Ship of the Week (Global) +Highest-impact PR across ALL projects. Identify by LOC and commit messages. + +### 3 Cross-Project Insights +What the global view reveals that no single-repo retro could show. + +### 3 Habits for Next Week +Considering the full cross-project picture. + +--- + +### Global Step 8: Load history & compare + +```bash +ls -t ~/.gstack/retros/global-*.json 2>/dev/null | head -5 +``` + +**Only compare against a prior retro with the same `window` value** (e.g., 7d vs 7d). If the most recent prior retro has a different window, skip comparison and note: "Prior global retro used a different window — skipping comparison." + +If a matching prior retro exists, load it with the Read tool. Show a **Trends vs Last Global Retro** table with deltas for key metrics: total commits, LOC, sessions, streak, context switches/day. + +If no prior global retros exist, append: "First global retro recorded — run again next week to see trends." + +### Global Step 9: Save snapshot + +```bash +mkdir -p ~/.gstack/retros +``` + +Determine the next sequence number for today: +```bash +today=$(date +%Y-%m-%d) +existing=$(ls ~/.gstack/retros/global-${today}-*.json 2>/dev/null | wc -l | tr -d ' ') +next=$((existing + 1)) +``` + +Use the Write tool to save JSON to `~/.gstack/retros/global-${today}-${next}.json`: + +```json +{ + "type": "global", + "date": "2026-03-21", + "window": "7d", + "projects": [ + { + "name": "gstack", + "remote": "https://github.com/garrytan/gstack", + "commits": 47, + "insertions": 3200, + "deletions": 800, + "sessions": { "claude_code": 15, "codex": 3, "gemini": 0 } + } + ], + "totals": { + "commits": 182, + "insertions": 15300, + "deletions": 4200, + "projects": 5, + "active_days": 6, + "sessions": { "claude_code": 48, "codex": 8, "gemini": 3 }, + "global_streak_days": 52, + "avg_context_switches_per_day": 2.1 + }, + "tweetable": "Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d" +} +``` + +--- + ## Compare Mode When the user runs `/retro compare` (or `/retro compare 14d`): @@ -761,3 +965,4 @@ When the user runs `/retro compare` (or `/retro compare 14d`): - Treat merge commits as PR boundaries - Do not read CLAUDE.md or other docs — this skill is self-contained - On first run (no prior retros), skip comparison sections gracefully +- **Global mode:** Does NOT require being inside a git repo. Saves snapshots to `~/.gstack/retros/` (not `.context/retros/`). Gracefully skip AI tools that aren't installed. Only compare against prior global retros with the same window value. If streak hits 365d cap, display as "365+ days". diff --git a/retro/SKILL.md.tmpl b/retro/SKILL.md.tmpl index b3fe8046..e61895f9 100644 --- a/retro/SKILL.md.tmpl +++ b/retro/SKILL.md.tmpl @@ -41,6 +41,8 @@ When the user types `/retro`, run this skill. - `/retro 30d` — last 30 days - `/retro compare` — compare current window vs prior same-length window - `/retro compare 14d` — compare with explicit window +- `/retro global` — cross-project retro across all AI coding tools (7d default) +- `/retro global 14d` — cross-project retro with explicit window ## Instructions @@ -48,17 +50,21 @@ Parse the argument to determine the time window. Default to 7 days if no argumen **Midnight-aligned windows:** For day (`d`) and week (`w`) units, compute an absolute start date at local midnight, not a relative string. For example, if today is 2026-03-18 and the window is 7 days: the start date is 2026-03-11. Use `--since="2026-03-11T00:00:00"` for git log queries — the explicit `T00:00:00` suffix ensures git starts from midnight. Without it, git uses the current wall-clock time (e.g., `--since="2026-03-11"` at 11pm means 11pm, not midnight). For week units, multiply by 7 to get days (e.g., `2w` = 14 days back). For hour (`h`) units, use `--since="N hours ago"` since midnight alignment does not apply to sub-day windows. -**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare`, or `compare` followed by a number and `d`/`h`/`w`, show this usage and stop: +**Argument validation:** If the argument doesn't match a number followed by `d`, `h`, or `w`, the word `compare` (optionally followed by a window), or the word `global` (optionally followed by a window), show this usage and stop: ``` -Usage: /retro [window] +Usage: /retro [window | compare | global] /retro — last 7 days (default) /retro 24h — last 24 hours /retro 14d — last 14 days /retro 30d — last 30 days /retro compare — compare this period vs prior period /retro compare 14d — compare with explicit window + /retro global — cross-project retro across all AI tools (7d default) + /retro global 14d — cross-project retro with explicit window ``` +**If the first argument is `global`:** Skip the normal repo-scoped retro (Steps 1-14). Instead, follow the **Global Retrospective** flow at the end of this document. The optional second argument is the time window (default 7d). This mode does NOT require being inside a git repo. + ### Step 1: Gather Raw Data First, fetch origin and identify the current user: @@ -504,6 +510,204 @@ Small, practical, realistic. Each must be something that takes <5 minutes to ado --- +## Global Retrospective Mode + +When the user runs `/retro global` (or `/retro global 14d`), follow this flow instead of the repo-scoped Steps 1-14. This mode works from any directory — it does NOT require being inside a git repo. + +### Global Step 1: Compute time window + +Same midnight-aligned logic as the regular retro. Default 7d. The second argument after `global` is the window (e.g., `14d`, `30d`, `24h`). + +### Global Step 2: Run discovery + +Locate and run the discovery script using this fallback chain: + +```bash +DISCOVER_BIN="" +[ -x ~/.claude/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=~/.claude/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && [ -x .claude/skills/gstack/bin/gstack-global-discover ] && DISCOVER_BIN=.claude/skills/gstack/bin/gstack-global-discover +[ -z "$DISCOVER_BIN" ] && which gstack-global-discover >/dev/null 2>&1 && DISCOVER_BIN=$(which gstack-global-discover) +[ -z "$DISCOVER_BIN" ] && [ -f bin/gstack-global-discover.ts ] && DISCOVER_BIN="bun run bin/gstack-global-discover.ts" +echo "DISCOVER_BIN: $DISCOVER_BIN" +``` + +If no binary is found, tell the user: "Discovery script not found. Run `bun run build` in the gstack directory to compile it." and stop. + +Run the discovery: +```bash +$DISCOVER_BIN --since "" --format json 2>/tmp/gstack-discover-stderr +``` + +Read the stderr output from `/tmp/gstack-discover-stderr` for diagnostic info. Parse the JSON output from stdout. + +If `total_sessions` is 0, say: "No AI coding sessions found in the last . Try a longer window: `/retro global 30d`" and stop. + +### Global Step 3: Run git log on each discovered repo + +For each repo in the discovery JSON's `repos` array, find the first valid path in `paths[]` (directory exists with `.git/`). If no valid path exists, skip the repo and note it. + +**For local-only repos** (where `remote` starts with `local:`): skip `git fetch` and use the local default branch. Use `git log HEAD` instead of `git log origin/$DEFAULT`. + +**For repos with remotes:** + +```bash +git -C fetch origin --quiet 2>/dev/null +``` + +Detect the default branch for each repo: first try `git symbolic-ref refs/remotes/origin/HEAD`, then check common branch names (`main`, `master`), then fall back to `git rev-parse --abbrev-ref HEAD`. Use the detected branch as `` in the commands below. + +```bash +# Commits with stats +git -C log origin/$DEFAULT --since="T00:00:00" --format="%H|%aN|%ai|%s" --shortstat + +# Commit timestamps for session detection, streak, and context switching +git -C log origin/$DEFAULT --since="T00:00:00" --format="%at|%aN|%ai|%s" | sort -n + +# Per-author commit counts +git -C shortlog origin/$DEFAULT --since="T00:00:00" -sn --no-merges + +# PR numbers from commit messages +git -C log origin/$DEFAULT --since="T00:00:00" --format="%s" | grep -oE '#[0-9]+' | sort -n | uniq +``` + +For repos that fail (deleted paths, network errors): skip and note "N repos could not be reached." + +### Global Step 4: Compute global shipping streak + +For each repo, get commit dates (capped at 365 days): + +```bash +git -C log origin/$DEFAULT --since="365 days ago" --format="%ad" --date=format:"%Y-%m-%d" | sort -u +``` + +Union all dates across all repos. Count backward from today — how many consecutive days have at least one commit to ANY repo? If the streak hits 365 days, display as "365+ days". + +### Global Step 5: Compute context switching metric + +From the commit timestamps gathered in Step 3, group by date. For each date, count how many distinct repos had commits that day. Report: +- Average repos/day +- Maximum repos/day +- Which days were focused (1 repo) vs. fragmented (3+ repos) + +### Global Step 6: Per-tool productivity patterns + +From the discovery JSON, analyze tool usage patterns: +- Which AI tool is used for which repos (exclusive vs. shared) +- Session count per tool +- Behavioral patterns (e.g., "Codex used exclusively for myapp, Claude Code for everything else") + +### Global Step 7: Aggregate and generate narrative + +Structure the output as: + +--- + +**Tweetable summary** (first line, before everything else): +``` +Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d +``` + +## Global Engineering Retro: [date range] + +### Overview +| Metric | Value | +|--------|-------| +| Projects active | N | +| Total commits (all repos) | N | +| Total LOC | +N / -N | +| AI coding sessions | N (CC: X, Codex: Y, Gemini: Z) | +| Active days | N | +| Global shipping streak | N consecutive days | +| Context switches/day | N avg (max: M) | + +### Per-Project Breakdown +For each repo (sorted by commits descending): +- Repo name (with % of total commits) +- Commits, LOC, PRs merged, top contributor +- Key work (inferred from commit messages) +- AI sessions by tool + +### Cross-Project Patterns +- Time allocation across projects (% breakdown) +- Peak productivity hours aggregated across all repos +- Focused vs. fragmented days +- Context switching trends + +### Tool Usage Analysis +Per-tool breakdown with behavioral patterns: +- Claude Code: N sessions across M repos — patterns observed +- Codex: N sessions across M repos — patterns observed +- Gemini: N sessions across M repos — patterns observed + +### Ship of the Week (Global) +Highest-impact PR across ALL projects. Identify by LOC and commit messages. + +### 3 Cross-Project Insights +What the global view reveals that no single-repo retro could show. + +### 3 Habits for Next Week +Considering the full cross-project picture. + +--- + +### Global Step 8: Load history & compare + +```bash +ls -t ~/.gstack/retros/global-*.json 2>/dev/null | head -5 +``` + +**Only compare against a prior retro with the same `window` value** (e.g., 7d vs 7d). If the most recent prior retro has a different window, skip comparison and note: "Prior global retro used a different window — skipping comparison." + +If a matching prior retro exists, load it with the Read tool. Show a **Trends vs Last Global Retro** table with deltas for key metrics: total commits, LOC, sessions, streak, context switches/day. + +If no prior global retros exist, append: "First global retro recorded — run again next week to see trends." + +### Global Step 9: Save snapshot + +```bash +mkdir -p ~/.gstack/retros +``` + +Determine the next sequence number for today: +```bash +today=$(date +%Y-%m-%d) +existing=$(ls ~/.gstack/retros/global-${today}-*.json 2>/dev/null | wc -l | tr -d ' ') +next=$((existing + 1)) +``` + +Use the Write tool to save JSON to `~/.gstack/retros/global-${today}-${next}.json`: + +```json +{ + "type": "global", + "date": "2026-03-21", + "window": "7d", + "projects": [ + { + "name": "gstack", + "remote": "https://github.com/garrytan/gstack", + "commits": 47, + "insertions": 3200, + "deletions": 800, + "sessions": { "claude_code": 15, "codex": 3, "gemini": 0 } + } + ], + "totals": { + "commits": 182, + "insertions": 15300, + "deletions": 4200, + "projects": 5, + "active_days": 6, + "sessions": { "claude_code": 48, "codex": 8, "gemini": 3 }, + "global_streak_days": 52, + "avg_context_switches_per_day": 2.1 + }, + "tweetable": "Week of Mar 14: 5 projects, 182 commits, 15.3k LOC | CC: 48, Codex: 8, Gemini: 3 | Focus: gstack (58%) | Streak: 52d" +} +``` + +--- + ## Compare Mode When the user runs `/retro compare` (or `/retro compare 14d`): @@ -537,3 +741,4 @@ When the user runs `/retro compare` (or `/retro compare 14d`): - Treat merge commits as PR boundaries - Do not read CLAUDE.md or other docs — this skill is self-contained - On first run (no prior retros), skip comparison sections gracefully +- **Global mode:** Does NOT require being inside a git repo. Saves snapshots to `~/.gstack/retros/` (not `.context/retros/`). Gracefully skip AI tools that aren't installed. Only compare against prior global retros with the same window value. If streak hits 365d cap, display as "365+ days". diff --git a/test/helpers/touchfiles.ts b/test/helpers/touchfiles.ts index 8fe2085a..8e2af37b 100644 --- a/test/helpers/touchfiles.ts +++ b/test/helpers/touchfiles.ts @@ -80,6 +80,9 @@ export const E2E_TOUCHFILES: Record = { 'retro': ['retro/**'], 'retro-base-branch': ['retro/**'], + // Global discover + 'global-discover': ['bin/gstack-global-discover.ts', 'test/global-discover.test.ts'], + // Document-release 'document-release': ['document-release/**'],