Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 140 additions & 15 deletions .agents/skills/status/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ description: Code Cannon: Summarize in-progress and recently completed work from

## Step 1 — Parse arguments

First, check whether `$ARGUMENTS` contains `--milestone` or `--sprint` (they are identical aliases).
First, check whether `$ARGUMENTS` contains `--milestone`, `--sprint`, or `--team`.

**Milestone mode:** If either flag is present, extract everything after `--milestone` or `--sprint` as the milestone name (trim leading/trailing whitespace; preserve internal spaces). Ignore any other arguments. Enter milestone mode (Steps M1–M3 below) and skip Steps 2–5.
**Milestone mode:** If `--milestone` or `--sprint` is present, extract everything after the flag as the milestone name (trim leading/trailing whitespace; preserve internal spaces). Ignore any other arguments. Enter milestone mode (Steps M1–M3 below) and skip Steps 2–6.

Examples:
- `--milestone Sprint 4` → milestone name = `Sprint 4`
- `--sprint Sprint 4` → milestone name = `Sprint 4`
- `--milestone Q2 Release` → milestone name = `Q2 Release`
- `--milestone 12` → milestone name = `12`

**Personal mode** (no `--milestone` / `--sprint` flag): determine:
**Team mode:** If `--team` is present, enter team mode (Steps T1–T3 below) and skip Steps 2–6. `--team` is mutually exclusive with `--milestone`/`--sprint` and username arguments. If both are present, report the conflict and stop.

**Personal mode** (no `--milestone` / `--sprint` / `--team` flag): determine:

- **subject**: default `@me`. If the argument starts with `@` or is a plain word that is not a number, treat it as a GitHub username. Strip the leading `@` for `gh` commands that do not accept it (e.g. `gh pr list --author alice`); keep it for display.
- **lookback**: default `7`. If the argument is a number (digits only), use it as the lookback window in days.
Expand All @@ -28,14 +30,14 @@ No argument → subject = `@me`, lookback = `7`.

---

## Step 2 — Fetch GitHub data (run all three in parallel)
## Step 2 — Fetch GitHub data (run all in parallel)

Run these commands concurrently:

**Open PRs authored by subject:**
```bash
gh pr list --author <subject> --state open \
--json number,title,url,labels,milestone,baseRefName,body
--json number,title,url,labels,milestone,baseRefName,body,reviewDecision,statusCheckRollup,updatedAt,mergeable,isDraft
```

**Recently merged PRs (last `<lookback>` days):**
Expand All @@ -48,8 +50,15 @@ Filter the results to keep only entries where `mergedAt` is within the last `<lo
**Open issues assigned to subject:**
```bash
gh issue list --assignee <subject> --state open \
--json number,title,url,labels,milestone
--json number,title,url,labels,milestone,updatedAt
```

**PRs requesting your review** (only when subject is `@me`):
```bash
gh pr list --search "review-requested:@me" --state open \
--json number,title,url,author,updatedAt
```
Skip this query when viewing another user's status.

If any `gh` command exits with a non-zero status (including auth errors), report the error message and stop. Do not retry.

Expand Down Expand Up @@ -78,9 +87,38 @@ Using the data from Steps 2 and 3, classify each item:
- **In progress** — open PRs. For each, attempt to identify a linked issue number from the PR body (look for `#N`, `closes #N`, `fixes #N`, `issue #N`). If found, cross-reference with open issues.
- **Done** — merged PRs within the lookback window.
- **Up next** — open issues that are NOT associated with any open PR (i.e. no open PR body references their issue number).
- **Needs your review** — PRs from the review-requested query (only when subject is `@me`).

An open issue that IS linked from an open PR body appears under "In progress" alongside that PR, not under "Up next".

### 4a — Derive health badges

For each open PR, derive the following badges:

**Draft status:**
- If `isDraft` is `true` → `[draft]`

**CI check status** (from `statusCheckRollup`):
- All checks have `status: COMPLETED` and `conclusion: SUCCESS` → `✅ checks passing`
- Any check has `conclusion: FAILURE` → `❌ checks failing`
- Checks are still running or have other states → `⏳ checks pending`
- No checks configured → omit badge

**Review decision** (from `reviewDecision`):
- `APPROVED` → `✅ approved`
- `CHANGES_REQUESTED` → `🔄 changes requested`
- `REVIEW_REQUIRED` or empty → `⏳ awaiting review`

**Merge conflict** (from `mergeable`):
- `CONFLICTING` → `⚠️ conflicts`
- `MERGEABLE` or `UNKNOWN` → omit badge

### 4b — Flag stale items

For each open PR and open issue, check `updatedAt`. If the item has not been updated within `14` days (default: 14; disabled when set to 0), flag it as stale. Record the last-updated date and the number of days since the last update.

A stale item gets an inline `⚠️ stale (<N>d)` badge appended after any other badges.

---

## Step 5 — Output the summary
Expand All @@ -90,29 +128,43 @@ Print a formatted summary. Use this structure:
```
## Status for <subject> — last <lookback> days

<N> in progress · <N> done · <N> up next[ · <N> need your review]

### In progress
- #<number> <title> [<labels>] [<milestone>]
PR: <url>
- #<number> <title> [<labels>] [<milestone>] [draft]
PR: <url> · <check badge> · <review badge>[ · <conflict badge>][ · <stale badge>]
Linked issue: #<number> (if found)

### Done
- #<number> <title> [<labels>] — merged <date>
PR: <url>

### Needs your review
- #<number> <title> (by @<author>)
PR: <url>

### Up next
- #<number> <title> [<labels>] [<milestone>]
- #<number> <title> [<labels>] [<milestone>][ · <stale badge>]
Issue: <url>

### ⚠️ Stale
- #<number> <title> — last updated <date> (<N> days ago)

---
Local commits (current branch):
<git log output, or "skipped — not in a git repo">
```

Rules:
- **Summary counts line**: show immediately after the heading. Omit zero-count segments (e.g., if nothing is done, skip that segment). "need your review" only appears when subject is `@me` and the count is > 0.
- **Health badges**: show on the second line of each "In progress" item, after the PR URL, separated by ` · `. Omit individual badges that don't apply (e.g., no conflict badge if mergeable).
- **Draft badge**: show `[draft]` inline in the first line of draft PRs, before any other badges.
- **Stale section**: a dedicated section at the bottom (before "Local commits") listing all stale items from any section, with their last-updated date and age. This gives a consolidated view. Individual items also get the inline `⚠️ stale (<N>d)` badge in their own sections.
- **"Needs your review" section**: only shown when subject is `@me` and there are PRs requesting review. Placed between "Done" and "Up next".
- Omit any section that has no items — do not show an empty heading.
- Show labels only if present; show milestone only if present.
- Dates use `YYYY-MM-DD` format.
- If all three GitHub sections are empty, print: `Nothing found for <subject> in the last <lookback> days.`
- If all GitHub sections are empty, print: `Nothing found for <subject> in the last <lookback> days.`

Do not post, comment, write files, or take any action. Output only.

Expand Down Expand Up @@ -160,6 +212,7 @@ Evaluate the following conditions **in order**. Use the **first** match:
| 1 | On a `feature/*` branch with uncommitted changes (`git status --porcelain` is non-empty) | `What's next: You have uncommitted changes on \`<branch>\`. When ready, run \`/submit-for-review\`.` |
| 2 | On a `feature/*` branch with an open PR that has `reviewDecision: APPROVED` and all status checks are `COMPLETED` | `What's next: PR #<number> is approved and checks pass. Consider running \`/deploy\`.` |
| 3 | On a `feature/*` branch with an open PR (any other review/check state) | `What's next: PR #<number> (<title>) is open and awaiting review.` |
| 3.5 | Subject is `@me` and there are PRs requesting your review (from Step 2 query) | Append to the current suggestion (or show standalone if no higher priority matched): `You also have <N> PR(s) awaiting your review.` |
| 4 | On a `feature/*` branch with no open PR and clean working tree | `What's next: No open PR for \`<branch>\`. Run \`/submit-for-review\` to open one.` |
| 5 | On the integration branch (`dev`, `develop`, or `main` when no integration branch exists) with unreleased commits (rev-list count > 0 since last tag) | `What's next: <N> commit(s) on \`<branch>\` since \`<tag>\`. Run \`/deploy\` when ready to release.` |
| 6 | No open PRs, no open issues assigned to subject | `What's next: Nothing in progress. Run \`/start\` to begin new work.` |
Expand Down Expand Up @@ -195,10 +248,11 @@ If this command fails for any reason (milestone not found, auth error, etc.), re

### Step M2 — Classify issues

Fetch all open PRs to detect which issues are in progress:
Fetch all open PRs to detect which issues are in progress (with health fields):

```bash
gh pr list --state open --json number,title,body,baseRefName
gh pr list --state open \
--json number,title,body,baseRefName,reviewDecision,statusCheckRollup,mergeable,isDraft
```

Group issues into three buckets:
Expand All @@ -207,6 +261,8 @@ Group issues into three buckets:
- **In progress** — `state: open` AND the issue number appears in any open PR body (look for `#<number>`, `closes #<number>`, `fixes #<number>`, `issue #<number>`)
- **Not started** — `state: open` AND no open PR body references the issue number

For in-progress issues, derive health badges from the linked PR using the same rules as Step 4a (check status, review decision, draft, conflict).

### Step M3 — Output the summary

```
Expand All @@ -215,8 +271,8 @@ Group issues into three buckets:
<Y> of <total> issues closed · <Z> in progress · <W> not started

### In progress (<Z>)
- #<number> <title> [@<assignee>] [<milestone>]
<url>
- #<number> <title> [@<assignee>] [<milestone>][ [draft]]
<url> · <check badge> · <review badge>[ · <conflict badge>]

### Not started (<W>)
- #<number> <title> [@<assignee>]
Expand All @@ -229,16 +285,85 @@ Rules:
- Show "In progress" first, then "Not started", then "Done"
- Show assignee only if present; omit if unassigned
- Show URLs only for in-progress items; omit URLs for closed issues
- Show health badges on in-progress items (same derivation as Step 4a)
- If a section has no items, omit it entirely

Do not post, comment, write files, or take any action. Output only.

---

## Team mode (Steps T1–T3)

Only entered when `--team` is detected in Step 1.

### Step T1 — Fetch all open work (run both in parallel)

```bash
gh pr list --state open --limit 100 \
--json number,title,url,author,labels,milestone,baseRefName,body,reviewDecision,statusCheckRollup,updatedAt,mergeable,isDraft
```

```bash
gh issue list --state open --limit 200 \
--json number,title,url,assignees,labels,milestone,updatedAt
```

If either command fails, report the error and stop.

### Step T2 — Group and classify

Group items by person:
- PRs are grouped by `author.login`
- Issues are grouped by assignee (first assignee if multiple). Issues with no assignee go into an "Unassigned" group.

Within each person's group, classify items the same way as personal mode (Step 4):
- **In progress** — open PRs (and linked issues)
- **Up next** — open issues not linked from any open PR

Derive health badges (Step 4a) and flag stale items (Step 4b) for all items.

### Step T3 — Output the team summary

```
## Team status

<N> open PRs · <N> open issues · <N> people

### @<person> (<N> in progress, <N> up next)
- #<number> <title> — PR <check badge> · <review badge>[ · <conflict badge>][ · <stale badge>][ [draft]]
<url>
- #<number> <title> [up next][ · <stale badge>]

### @<person> (<N> in progress, <N> up next)
...

### Unassigned (<N>)
- #<number> <title>
<url>

### ⚠️ Stale
- #<number> <title> (@<person>) — last updated <date> (<N> days ago)
```

Rules:
- Sort people alphabetically by username
- Within each person, show in-progress items first, then up-next items
- Show health badges on PR items (same format as personal mode)
- Show `[draft]` on draft PRs
- Tag up-next items with `[up next]` for visual distinction
- "Unassigned" section appears at the bottom, only if there are unassigned issues
- "Stale" section consolidates all stale items across all people
- Omit any section or group with no items
- No "What's next" section in team mode

Do not post, comment, write files, or take any action. Output only.

---

## Hard rules

- Never write to GitHub (no comments, labels, issue updates, or PR changes).
- If `gh` is unauthenticated or any fetch fails, report the error and stop immediately.
- Do not retry failed commands.
- Strip the leading `@` from the subject when passing to `gh` flags that do not accept it.
<!-- generated by CodeCannon/sync.sh | skill: status | adapter: codex | hash: b942c6b6 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate -->
<!-- generated by CodeCannon/sync.sh | skill: status | adapter: codex | hash: 03a99a92 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate -->
Loading