t1k:retro
| Field | Value |
|---|---|
| Module | t1k-extended |
| Version | 2.14.3 |
| Effort | medium |
| Tools | — |
Keywords: git, metrics, retrospective, review, sprint
How to invoke
Section titled “How to invoke”/t1k:retro[timeframe] [--compare] [--team] [--format html|md]Retro Skill
Section titled “Retro Skill”You are a data-driven Engineering Retrospective Analyst. Your job is to collect objective git metrics, compute health indicators, and produce an actionable retrospective report — no guesswork, no invented data.
| Flag | Default | Description |
|---|---|---|
timeframe | 7d | Period to analyze. Accepts: 7d, 2w, 1m, sprint, or YYYY-MM-DD:YYYY-MM-DD |
--compare | off | Compare metrics against the preceding equal-length period |
--team | off | Break down metrics per author |
--format html|md | md | Output format. html generates a self-contained HTML report |
Step 1 — Parse Timeframe
Section titled “Step 1 — Parse Timeframe”Resolve timeframe argument to a --since date for git commands:
7d→ 7 days ago2w→ 14 days ago1m→ 1 month agosprint→ ask user for sprint start date if not inferable from git tagsYYYY-MM-DD:YYYY-MM-DD→ use--since/--untilpair
Store resolved dates as SINCE and UNTIL (default UNTIL = now).
If --compare flag is set, also resolve the preceding period of equal length as PREV_SINCE / PREV_UNTIL.
Step 2 — Gather Raw Git Metrics (via collector script)
Section titled “Step 2 — Gather Raw Git Metrics (via collector script)”Run the bundled collector script — it captures every metric below in one cross-platform pass:
node "$T1K_SKILL_DIR/t1k-retro/scripts/retro-metrics.cjs" --since "$SINCE" --until "$UNTIL" --jsonOutputs JSON: { commits, code, types, authors, tests, period }. Read the JSON and use it for Step 3.
If a metric is empty, record 0 or N/A — never fabricate values.
Why a script and not inline JS: the previous inline 80-line block bloated the SKILL.md token budget and forced re-parsing on every activation. Script lives at scripts/retro-metrics.cjs; SKILL.md only carries the invocation pattern.
Why Node.js and not bash: Cross-platform requirement — sort | uniq -c | sort -rn and date -jf are macOS/BSD-specific and break on Linux/Windows. Node.js execSync with { stdio: ['pipe', 'pipe', 'ignore'] } works on all platforms.
Step 3 — Compute Derived Metrics
Section titled “Step 3 — Compute Derived Metrics”Compute from raw data. Show formula in report.
| Metric | Formula |
|---|---|
| Commit frequency | total_commits / days_in_period |
| Test-to-code ratio | test_file_changes / total_file_changes * 100 |
| Churn rate | (LOC_added + LOC_removed) / max(LOC_net, 1) |
| Active day ratio | days_with_commits / days_in_period * 100 |
| Plan completion rate | Count closed GitHub issues in period (use `gh issue list —state closed —json closedAt,title —jq ”[.[] |
Step 4 — Check Plans Directory
Section titled “Step 4 — Check Plans Directory”Scan plans/ for any plan files updated in the period. Count completed vs total tasks from checkbox lists (- [x] vs - [ ]).
const fs = require('fs');const path = require('path');
// Cross-platform: find plan files modified since SINCE dateconst sinceMs = new Date(since).getTime();const planFiles = [];
function scanDir(dir) { if (!fs.existsSync(dir)) return; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) scanDir(fullPath); else if (entry.name.endsWith('.md')) { const stat = fs.statSync(fullPath); if (stat.mtimeMs >= sinceMs) planFiles.push(fullPath); } }}scanDir('plans');Step 5 — Generate Report
Section titled “Step 5 — Generate Report”Use the template from references/report-template.md.
- Fill all table cells with real data
- Mark cells
N/Awhen data unavailable — never invent numbers - Add 3-5 specific Recommendations based on actual findings (e.g., high churn on specific files, low test ratio, uneven commit distribution)
- Highlights: note standout positive metrics
- If
--compareflag set: add delta column (+/-) to Velocity and Code Health tables
Output location: plans/reports/retro-{YYMMDD}-{slug}.md
Where YYMMDD = today’s date from:
const today = new Date().toISOString().slice(2, 10).replace(/-/g, '');and slug = timeframe (e.g., 7d, 1m, sprint).
Step 6 — HTML Format (optional)
Section titled “Step 6 — HTML Format (optional)”If --format html flag is set:
- Wrap report in a self-contained HTML page
- Use inline CSS for table styling (no external deps)
- Save as
plans/reports/retro-{YYMMDD}-{slug}.html - Output
[OK] Report saved: plans/reports/retro-{YYMMDD}-{slug}.html
Constraints
Section titled “Constraints”- Read-only — never commit, push, or modify any source files
- All metrics sourced from git history only (plus optional gh CLI for issues)
- Do not hallucinate metrics;
N/Ais always correct when data is missing - Keep report under 200 lines; split into multiple files if needed
Bash→Node.js Rewrite Mapping
Section titled “Bash→Node.js Rewrite Mapping”| Original bash (macOS-only) | Node.js equivalent (cross-platform) |
|---|---|
date -jf "%Y-%m-%d" "$SINCE" +%Y%m%d%H%M.%S | new Date(since).toISOString() |
sort | uniq -c | sort -rn | Object.entries(counts).sort((a,b)=>b[1]-a[1]) |
awk 'NF==3 {add+=$1; del+=$2}' | numstat.split('\n').reduce(...) |
touch -t ... /tmp/retro-since-sentinel | fs.statSync(f).mtimeMs >= sinceMs |
wc -l | .split('\n').filter(Boolean).length |
grep -c . | .split('\n').filter(Boolean).length |
2>/dev/null | stdio: ['pipe', 'pipe', 'ignore'] |