| name | team-report |
| description | Produce a comprehensive, leadership-ready Markdown report on a software delivery team's performance using the local `dev-metrics` CLI. Pulls DORA, PR cycle, flow, review health, quality, CI, sprint, and risk metrics for a given team and window; synthesises cross-metric patterns into a prioritised action list (what's working, what's broken, what to fix first) — not just a dump of numbers. Use this skill whenever the user asks for a team performance report, sprint retrospective prep, weekly or monthly metrics summary, delivery health check, engineering scorecard, executive brief on a team, or says anything like "how is team X doing", "where are our bottlenecks", "give me the metrics for Y" — even when they don't explicitly say "report". This is the right tool any time the request calls for synthesised insight across more than one or two dev-metrics numbers. |
Team performance report
You are generating an operator → leadership brief on a software delivery team, using the dev-metrics CLI that lives in this repo. The goal is a 5–8 page Markdown report that is insights-first, numbers-supporting — a VP reading page 1 should know what's working and what's broken. Page 2+ supplies the evidence.
This skill is the heavy-synthesis counterpart to running the raw CLI. The CLI emits numbers; you turn them into a story about the team's delivery health and a prioritised action list. That synthesis is the reason to use this skill at all; without it we'd just be dumping JSON.
When the user invokes you
Typical phrasings:
- "prepare a team performance report for platform last month"
- "give me a weekly metrics summary on backend-team"
- "how is team X doing over the last 30 days"
- "sprint retrospective brief for the mobile team"
- "where are our bottlenecks this quarter"
Parse out:
- team — the team id as configured in
dev-metrics.config.yaml's teams: section. Defaults: if the user says "our team" / "the team" and only one team is configured, use that one. If multiple teams and no disambiguator, ask.
- window — if the user gives a relative phrase like "last month" / "last 7 days" / "this quarter", map to a
--from relative-date shorthand (30d / 7d / 3m / 1y) and leave --to at the default (now). If absolute dates are given, pass them through. If nothing is specified, default to 30 days.
Always echo your resolved scope (team + window) before starting the data collection. If the user's phrasing was ambiguous (e.g., "last month" on the 4th → do they mean calendar-last-month or 30d?), state your interpretation in one line so they can correct.
Workflow
Follow these steps in order. The key is: collect first, synthesise second — never emit a partial report.
1. Verify the DB has relevant data
pnpm dev-metrics scope --team <TEAM> --from <N>d --json
Parse the JSON. If data.prs === 0 && data.issues === 0, stop and tell the user the DB is empty for the scope — usually means the team config is wrong, or dev-metrics sync hasn't run yet.
2. Fan out the metric collection in parallel
Run scripts/collect.sh with the resolved team + window. It shells out ~24 CLI invocations in parallel and writes each response to a workspace directory under /tmp/:
bash .claude/skills/team-report/scripts/collect.sh <TEAM> <FROM> [TO]
The script emits one line like workspace=/tmp/dev-metrics-report-<team>-<iso> — that path contains {dora,pr-cycle,flow,...}.json + trends/{metric}.json + scope.json. Every downstream step reads from there.
If any individual CLI call fails, the script logs the error to errors.log in the workspace but keeps going so a broken metric doesn't torpedo the whole report. In your report, gracefully note "couldn't compute X because Y" for any failed metric rather than hiding it.
3. Load the interpretation reference
Read references/metric-interpretation.md. It contains red/amber/green threshold bands per metric (sourced from DORA state-of-DevOps + LinearB + Flow Framework canon) so your synthesis has a reference frame rather than vibes. Without this, your "is 600s pickup time bad?" judgment is guesswork.
4. Synthesise bottlenecks — cross-metric patterns
This is the step that earns the skill its keep. Walk the collected data looking for:
- Cascades: low CI pass rate ⇒ long PR pickup (engineers afraid to review flaky tests) ⇒ sprint completion drop.
- Honesty signals: any metric where
sampleN < 30 → red n-badge territory → flag as "inconclusive, not enough data"; don't make claims.
- Prereq misses: any envelope with
prereq.ok === false → surface the specific reason (e.g., "no Jira board configured for CFD").
- Trend + snapshot coupling: a P85 that looks OK today but trended up 50% over 12 weeks is a much worse finding than a slightly higher P85 that's trending down.
- Outlier ping-pong: if
ticket_hops outliers exist, investigate whether they correlate with long cycle time or sprint scope change.
- Review-coverage paired with depth: high coverage + very low depth means rubber-stamp reviews; high coverage + high depth is the actual signal of a healthy review culture.
Write 3–5 prioritised bottlenecks with concrete reasoning, not generic platitudes. For each: what the data says, why it matters, what to try next. Order them by estimated impact / reversibility.
5. Assemble the report
Use the template in the next section, verbatim. Fill in every section — if a section is "no data" say so explicitly, don't skip.
6. Write and announce the output
Write the report to:
/tmp/dev-metrics-report-<team>-<ISO8601-timestamp>.md
Example: /tmp/dev-metrics-report-platform-2026-04-18T20-15-03Z.md
Print the full path as the last line of your response so the operator can open it. Also print a one-paragraph executive TL;DR to the chat (not a sales pitch — the actual top finding) so the operator can decide whether to open the file.
Report template
Use this exact structure. The numbers in [brackets] are filled from the collected JSON.
# Team performance report — [Team Name]
**Window:** [FROM] → [TO] ([N] days)
**Generated:** [ISO8601 timestamp]
**Scope:** [N repos] · [N Jira projects] · [N PRs merged] · [N issues resolved]
---
## TL;DR
[3–5 sentences. Lead with the single most important finding. Include the top
bottleneck, the top trend delta (good or bad), and the biggest "what to fix
first" call. Use specific numbers. No meta-commentary.]
## Key bottlenecks (prioritised)
1. **[Headline]** — [data:specific-number-with-n-and-trend]. [Why it
matters.] [What to try.]
2. **[Headline]** — …
3. **[Headline]** — …
## DORA four keys
| Metric | Value | Trend (12w) | n | Band |
|---|---|---|---|---|
| Deployment Frequency | [DF/week] | [↑/→/↓ Δ%] | [n] | [🟢🟡🔴] |
| Lead Time for Changes | P50 [X] · P85 [Y] | [trend on P85] | [n] | [band] |
| Change Failure Rate | [%] | [trend] | [n] | [band] |
| Mean Time to Restore | P50 [X] · P85 [Y] | [trend] | [n] | [band] |
**Deploy signal used:** [deployments_api | default_branch_merges | release_tags] per repo.
**Reading:** [2–3 sentences on what the DORA quartet is telling us.]
## Flow & delivery
- **Throughput:** [items/week P50] · [12w trend]
- **WIP:** [mean] · [Little's Law consistency: ✅/⚠️]
- **Cycle time by issue type:** [top 3 types with P50/P85 — each its own row]
- **Flow efficiency:** [X%] · [prereq: ✅ configured / ⚠️ no waiting states]
- **Sprint say-do ratio:** median [X%] over [N] sprints · [trend]
- **CI pass rate:** [%] · duration P50 [X] · [N flaky SHAs] · [trend]
**Reading:** [2–3 sentences.]
## PR cycle time breakdown
| Stage | P50 | P85 | P95 | n | Trend (P85, 12w) |
|---|---|---|---|---|---|
| Coding | … | … | … | … | … |
| Pickup | … | … | … | … | … |
| Review | … | … | … | … | … |
| Merge | … | … | … | … | … |
**Reading:** [Which stage dominates? Is it trending worse?]
## Review health (coverage + depth always paired)
- **Coverage:** [X%] of merged PRs had ≥1 non-author review · n=[N]
- **Depth:** P50 [X] comments/PR · P85 [Y] · [paired reading — are reviews substantive or rubber-stamped?]
- **Requested changes rate:** [%] of PRs went through CHANGES_REQUESTED · [trend]
- **Review iterations:** median [X] revision cycles per PR · [trend]
## Quality signals
- **Reopen rate:** [X%] of closed issues reopened — n=[N]
- **Revert rate:** [X%] of merged PRs reverted — n=[N]
[One sentence interpretation.]
## Risk surface — outliers, bottlenecks, hotspots
- **PR size outliers:** [N PRs ≥ 1000 LOC] — link drill-through with `dev-metrics pr <id>`
- **PR age outliers:** [N PRs open > 14d]
- **Ticket cycle outliers:** [N issues > 30d cycle time]
- **Ticket hops (ping-pong):** [N issues with ≥10 status transitions] — [top 3 by count with keys]
- **Stale PRs (open, no activity ≥ 7d):** [N]
- **Reviewer load:** [operational triage only — see docs/anti-patterns.md]
- **File hotspots:** [top 5 churn-×-complexity files]
## Anti-pattern guardrails
_This report contains **zero** per-engineer rankings, **no lone arithmetic means** on distributional metrics, and every metric carries its sample-size n-badge and prereq status. Reviewer-load figures above are operational triage only per `docs/anti-patterns.md`._
## Appendix — raw JSON
All per-metric envelopes are archived at `[workspace path]/` and reproducible with:
```bash
bash .claude/skills/team-report/scripts/collect.sh <TEAM> <FROM> [TO]
---
## Invariants — what this report must **never** do
These are the platform's anti-pattern commitments carried into the report format. They are non-negotiable.
- **No per-engineer ranking.** Ever. Reviewer load and drill-through PR/issue views are operational-triage, never performance evaluation. If a synthesis you're about to write implies "person X is slow" — stop and rewrite.
- **No lone arithmetic mean** on distributional metrics. Always pair with P50/P85/P95 (+ min/max in the appendix). The CLI never emits a bare `mean`; don't compute one yourself from raw data.
- **Respect small-N honesty.** If `sampleN < 30`, tag the finding "low confidence (n=X)" and soften the language. Claiming "pickup is getting worse" from 8 data points is dishonest.
- **Surface prereq misses.** If `prereq.ok === false` (e.g., flow efficiency with no waiting states configured, CFD with no board), do NOT silently skip — write "flow efficiency not computable: [reason]".
- **Pair coverage + depth.** Never report review coverage without depth, and never depth without coverage. They're two halves of one signal per `docs/anti-patterns.md`.
- **SPACE framing preserved.** Where space allows (pun unintended), note which SPACE dimensions each finding touches (e.g., "pickup time → E,C — slow feedback cycle + cross-engineer handoff friction"). Discourages collapsing delivery health into "the one number".
---
## Formatting conventions
- **Durations:** `d/h/m/s` pretty format, matching the CLI's own renderer. `1h20m` not `4800 seconds`.
- **Percentages:** one decimal place (`66.6%` not `66.6666%`).
- **Trend deltas:** `↑ 12%` / `→` / `↓ 8%` with an arrow + bare percentage. Trend is P85-vs-P85 12 weeks earlier for distributions, raw-value-vs-raw 12 weeks earlier for rates and counts.
- **Band glyphs:** 🟢 / 🟡 / 🔴 — see `references/metric-interpretation.md` for thresholds.
- **Links:** any specific PR or issue called out must include `dev-metrics pr <id>` / `dev-metrics issue <key>` in backticks so the reader can drill through.
---
## Edge cases
- **DB empty for scope** → stop after step 1 with a one-line explanation. Don't generate an empty report.
- **All metrics n=0** → generate a short "insufficient data" report with the scope summary + next-step suggestion ("extend the window or check team config").
- **Single-repo team** → the per-repo breakdown section collapses; just say "single-repo team: [name]".
- **No Jira projects configured** → omit sprint, CFD, time-in-status, quality (reopen_rate) sections with a one-liner.
- **Trend endpoint errors for some metrics** → the collect script logs to `errors.log`; in the report, show current values without trend arrows and footnote "12w trend unavailable for this metric".
- **Jumbo teams with 1000+ PRs** → the report stays one file; don't split. Prioritise ruthlessly in TL;DR and key bottlenecks; push detail to the appendix.
---
## Under the hood
- `scripts/collect.sh` — parallel CLI fan-out. ~24 invocations against the local SQLite DB via `dev-metrics get ... --json`. No HTTP, no `serve` running required.
- `references/metric-interpretation.md` — the threshold bands and reasoning. Read this before writing bottlenecks.
- The CLI itself — `dev-metrics list` shows every metric + one-line definition. `dev-metrics get <metric> --help` shows formula + prereqs + example.