mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-06 13:45:35 +02:00
feat: /retro global — cross-project retro using discovery engine
Adds Global Retrospective Mode to the /retro skill. When invoked as `/retro global`, skips the repo-scoped retro and instead uses gstack-global-discover to find all AI coding sessions across all tools, then runs git log on each discovered repo for a unified cross-project retrospective with global shipping streak and context-switching metrics.
This commit is contained in:
@@ -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 "<window>" --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 <window>. 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 <path> 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 `<default>` in the commands below.
|
||||
|
||||
```bash
|
||||
# Commits with stats
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%H|%aN|%ai|%s" --shortstat
|
||||
|
||||
# Commit timestamps for session detection, streak, and context switching
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%at|%aN|%ai|%s" | sort -n
|
||||
|
||||
# Per-author commit counts
|
||||
git -C <path> shortlog origin/$DEFAULT --since="<start_date>T00:00:00" -sn --no-merges
|
||||
|
||||
# PR numbers from commit messages
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>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 <path> 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".
|
||||
|
||||
+207
-2
@@ -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 "<window>" --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 <window>. 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 <path> 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 `<default>` in the commands below.
|
||||
|
||||
```bash
|
||||
# Commits with stats
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%H|%aN|%ai|%s" --shortstat
|
||||
|
||||
# Commit timestamps for session detection, streak, and context switching
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%at|%aN|%ai|%s" | sort -n
|
||||
|
||||
# Per-author commit counts
|
||||
git -C <path> shortlog origin/$DEFAULT --since="<start_date>T00:00:00" -sn --no-merges
|
||||
|
||||
# PR numbers from commit messages
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>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 <path> 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".
|
||||
|
||||
+207
-2
@@ -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 "<window>" --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 <window>. 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 <path> 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 `<default>` in the commands below.
|
||||
|
||||
```bash
|
||||
# Commits with stats
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%H|%aN|%ai|%s" --shortstat
|
||||
|
||||
# Commit timestamps for session detection, streak, and context switching
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>T00:00:00" --format="%at|%aN|%ai|%s" | sort -n
|
||||
|
||||
# Per-author commit counts
|
||||
git -C <path> shortlog origin/$DEFAULT --since="<start_date>T00:00:00" -sn --no-merges
|
||||
|
||||
# PR numbers from commit messages
|
||||
git -C <path> log origin/$DEFAULT --since="<start_date>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 <path> 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".
|
||||
|
||||
@@ -80,6 +80,9 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
'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/**'],
|
||||
|
||||
|
||||
Reference in New Issue
Block a user