diff --git a/.claude/skills/sprint-status/SKILL.md b/.claude/skills/sprint-status/SKILL.md index 5673405aa..5c1ac9b80 100644 --- a/.claude/skills/sprint-status/SKILL.md +++ b/.claude/skills/sprint-status/SKILL.md @@ -8,12 +8,33 @@ description: > when housekeeping feels off. Triggers on "sprint status", "cleanup sweep", "what's open", "sprint health". user-invocable: true +allowed-tools: Task, Read, Grep, Glob --- # Sprint Status -Produce a consistent, scannable sprint health report. Closed work scrolls -off the top; open work by team is visible at the bottom. +**Delegate this entire skill to a subagent** (general-purpose, model: haiku). + +When this skill is invoked, spawn a subagent using the Task tool: + +``` +Task( + subagent_type: "general-purpose", + model: "haiku", + prompt: "Run /sprint-status. Read the skill at + .claude/skills/sprint-status/SKILL.md for the full workflow + (below the --- separator), then execute it.", + description: "Sprint status report" +) +``` + +Present the subagent's output to the user verbatim. Do NOT run the +workflow yourself. + +--- + +The remainder of this file is the subagent's reference for executing +the workflow. ## Step 1 — Gather data @@ -28,7 +49,7 @@ tea pr list --login schweitz --repo jpmschweitzer/settled-reach --state open --o ``` The `sweep` command returns JSON with: -- `sprint` — id, name, status, goal +- `sprint` — id, name, goal - `progress` — total, done, pct - `by_status` — tickets grouped into done, review, in_progress, blocked, backlog - `by_team` — per-team counts @@ -57,10 +78,14 @@ Read `references/output-template.md` for the exact format spec. Render the report using data from steps 1-2. Key rules: - Sections ordered: Completed, In Review, In Progress, Blocked, Backlog - Sort tickets within sections by team then ticket ID -- Empty sections: show header with "(0)" and "(none)" -- Bookkeeping Issues table: merge ticket-side issues from `sweep` with - PR-side issues from step 2 +- Empty sections: show header with "(0)" and "(none)" — no empty table +- Bookkeeping Issues: two-column table (Issue, Fix) - Open Work by Team: summary table at the bottom +- Issue type labels: `stale_backlog` → "Stale backlog", + `unassigned_in_progress` → "Unassigned in_progress", + `assigned_but_done` → "Assigned but done", + `done_team_open_pr` → "Done team with open PR", + `orphan_pr` → "Orphan PR" ## Step 4 — Suggest actions diff --git a/.claude/skills/sprint-status/references/output-template.md b/.claude/skills/sprint-status/references/output-template.md index 74f51eab1..5976c1b39 100644 --- a/.claude/skills/sprint-status/references/output-template.md +++ b/.claude/skills/sprint-status/references/output-template.md @@ -1,7 +1,5 @@ # Sprint Status Output Template -Use this template exactly when formatting `/sprint-status` output. - ## Sprint {N}: {Theme} — Status Report **Goal:** {goal} @@ -44,11 +42,9 @@ Use this template exactly when formatting `/sprint-status` output. ### Bookkeeping Issues -| Issue | Detail | Fix | -|-------|--------|-----| -| {type} | {detail} | `{command}` | - -If no issues: "No bookkeeping issues found." +| Issue | Fix | +|-------|-----| +| {type}: {detail} | `{command}` | ### Open Work by Team @@ -56,15 +52,3 @@ If no issues: "No bookkeeping issues found." |------|---------|-------------|--------|---------|------| | {team} | {n} | {n} | {n} | {n} | {n} | | **Total** | **{n}** | **{n}** | **{n}** | **{n}** | **{n}** | - -## Rendering rules - -- Sections with 0 items: show header with "(0)" and a single line "(none)" — no empty table. -- Sort tickets within each section by team, then by ticket ID. -- Use the exact markdown table format above (pipe-separated, header row, separator row). -- Bookkeeping issue types map to human-readable labels: - - `unassigned_in_progress` → "Unassigned in_progress" - - `stale_backlog` → "Stale backlog" - - `assigned_but_done` → "Assigned but done" - - `done_team_open_pr` → "Done team with open PR" - - `orphan_pr` → "Orphan PR" diff --git a/db/connectors/sprint b/db/connectors/sprint index 8e60602fe..ff91da9ae 100755 --- a/db/connectors/sprint +++ b/db/connectors/sprint @@ -529,7 +529,6 @@ def cmd_sweep(args): "title": t["title"], "team": t.get("team") or "unassigned", "assigned_to": t.get("assigned_to"), - "priority": t["priority"], } if t["status"] == "done": by_status["done"].append(entry) @@ -559,22 +558,19 @@ def cmd_sweep(args): if t["status"] in ("in_progress", "review") and not t.get("assigned_to"): issues.append({ "type": "unassigned_in_progress", - "ticket_id": t["id"], - "detail": f"#{t['id']} is {t['status']} but has no agent assigned", + "detail": f"#{t['id']} unassigned {t['status']}", "fix": f"db/connectors/ticket assign {t['id']} ", }) if t["status"] == "backlog" and sprint["status"] == "active" and t["id"] not in blocked_by_map: issues.append({ "type": "stale_backlog", - "ticket_id": t["id"], - "detail": f"#{t['id']} still in backlog (unblocked, never started)", + "detail": f"#{t['id']} stale backlog", "fix": f"db/connectors/ticket status {t['id']} in_progress", }) if t["status"] == "done" and t.get("assigned_to"): issues.append({ "type": "assigned_but_done", - "ticket_id": t["id"], - "detail": f"#{t['id']} is done but still assigned to {t['assigned_to']}", + "detail": f"#{t['id']} done, still assigned", "fix": f"db/connectors/ticket unassign {t['id']}", }) @@ -584,11 +580,9 @@ def cmd_sweep(args): pct = int(done / total * 100) if total > 0 else 0 result = { - "ok": True, "sprint": { "id": sprint["id"], "name": sprint.get("name", f"Sprint {sprint['id']}"), - "status": sprint["status"], "goal": sprint.get("goal", ""), }, "progress": {"total": total, "done": done, "pct": pct},