add whats-next skill for batch ticket selection
Walks the pql initiative/epic tree, filters to unblocked tickets, optionally refines context via parallel agents, and transitions a confirmed batch to in_progress. Mirrors the existing pql skill's place in the planning flow so /whats-next is the natural counterpart to "what's the plan status". Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
---
|
||||
name: whats-next
|
||||
description: >
|
||||
Surface the best batch of tickets to pick up next from pql. Walks the
|
||||
initiative/epic tree, filters to unblocked work, refines context via
|
||||
parallel agents (or `pql ticket refine` for empty descriptions), and
|
||||
optionally activates the batch on a fresh branch. Use when the user
|
||||
says "what's next", "next batch", "pick up work", or invokes
|
||||
/whats-next. NOT triggered by "what should we work on" in a design
|
||||
context — that's a discussion, not a batch selection.
|
||||
user-invocable: true
|
||||
allowed-tools: Bash, Read, Grep, Glob, Agent, AskUserQuestion
|
||||
---
|
||||
|
||||
# What's Next
|
||||
|
||||
Dependency-driven batch selection against pql. Three steps:
|
||||
batch selection → refinement review → batch activation.
|
||||
|
||||
Pql is the single source of truth for tickets and decisions in this repo
|
||||
(see [pql skill](../pql/SKILL.md) and [`decisions/README.md`](../../../decisions/README.md)). Always run from the repo root.
|
||||
|
||||
## Step 0: Sync state
|
||||
|
||||
Decisions on disk may be ahead of pql.db. Always sync before reading:
|
||||
|
||||
```bash
|
||||
pql decisions sync
|
||||
```
|
||||
|
||||
If `pql` is missing, stop and tell the user — don't fall back to grep.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Batch Selection
|
||||
|
||||
### 1a. Find active top-level work
|
||||
|
||||
Pql has no `milestone` concept; **initiatives** (and large **epics**) play
|
||||
that role. List in-flight top-level work:
|
||||
|
||||
```bash
|
||||
pql ticket list --status in_progress --pretty
|
||||
pql ticket list --status ready --pretty
|
||||
```
|
||||
|
||||
If nothing is `in_progress` or `ready` at the initiative/epic level,
|
||||
fall back to `pql plan status --pretty` for a dashboard read and ask the
|
||||
user which area to advance.
|
||||
|
||||
### 1b. Build the work landscape
|
||||
|
||||
For each candidate epic or initiative, expand its children:
|
||||
|
||||
```bash
|
||||
pql ticket show <id> --with-children --pretty
|
||||
```
|
||||
|
||||
Collect every leaf ticket (story/task/bug) underneath. Deduplicate.
|
||||
|
||||
### 1c. Filter to unblocked tickets
|
||||
|
||||
For each leaf with status `ready` or `backlog`, check blockers:
|
||||
|
||||
```bash
|
||||
pql ticket show <id> --with-blockers --pretty
|
||||
```
|
||||
|
||||
A ticket is **unblocked** if every blocker is `done` or `cancelled`.
|
||||
Drop the rest.
|
||||
|
||||
### 1d. Rank and group
|
||||
|
||||
Rank unblocked tickets by:
|
||||
|
||||
1. **Priority** (critical > high > medium > low) — read from ticket fields.
|
||||
2. **Epic proximity to done** — for each epic parent, compute
|
||||
`done_children / total_children`. Higher ratio ranks higher: finishing
|
||||
an epic unlocks downstream work and tightens the board.
|
||||
3. **Fan-out** — tickets that unblock the most other tickets rank higher.
|
||||
Approximate by scanning `pql ticket list --status backlog --pretty`
|
||||
and counting how many list this ticket in their blockers (use
|
||||
`--with-blockers` per candidate, or read `--jsonl` once and reduce in
|
||||
memory).
|
||||
|
||||
Group into **epic-sized batches**: tickets sharing a `parent_id`, or a
|
||||
logical cluster if no shared parent. If nothing groups naturally, batch
|
||||
by area (the directory the work touches, e.g. `lib/src/pty/`).
|
||||
|
||||
### 1e. Show the board
|
||||
|
||||
```bash
|
||||
pql ticket board --pretty
|
||||
```
|
||||
|
||||
This is the "what's currently in flight" view — the user wants to see
|
||||
WIP before committing to more.
|
||||
|
||||
### 1f. Present the recommended batch
|
||||
|
||||
Show the user:
|
||||
|
||||
- The recommended batch — IDs, titles, priorities, parent epic.
|
||||
- **Why this batch** — which epic it advances, what it unblocks downstream.
|
||||
- Current board state (WIP count vs. ready/backlog).
|
||||
- One or two alternative batches worth considering.
|
||||
|
||||
Wait for user confirmation before Step 2.
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Ticket Refinement Review
|
||||
|
||||
Two cases — handle the cheap one first.
|
||||
|
||||
### 2a. Tickets with empty descriptions → use pql
|
||||
|
||||
If any ticket in the batch has no description, hand off to pql's
|
||||
built-in refinement flow:
|
||||
|
||||
```bash
|
||||
pql ticket refine list --pretty
|
||||
pql ticket refine next --pretty # full context for the next one
|
||||
pql ticket refine write T-NN '{"description":"..."}'
|
||||
```
|
||||
|
||||
Walk these with the user (AskUserQuestion per ticket if appropriate)
|
||||
before moving on.
|
||||
|
||||
### 2b. Tickets with descriptions → spawn refinement agents
|
||||
|
||||
For each ticket that already has a description but may still be
|
||||
under-specified, spawn one agent in parallel. Use `general-purpose`
|
||||
subagent_type (custom subagent_types lose SendMessage):
|
||||
|
||||
```
|
||||
Agent({
|
||||
subagent_type: "general-purpose",
|
||||
model: "sonnet",
|
||||
description: "Refine T-NN context",
|
||||
prompt: "You are the Refinement Manager for ticket T-NN.
|
||||
|
||||
Ticket: <title>
|
||||
Description: <body>
|
||||
Decision ref: <D-NN or Q-NN, if set>
|
||||
|
||||
Your job:
|
||||
1. Run `pql decisions show <decision_ref> --with-refs --pretty` and
|
||||
read the linked D/Q-record in decisions/<domain>.md.
|
||||
2. Grep decisions/questions-*.md for related Q-records.
|
||||
3. Verify referenced files, classes, and APIs actually exist in the
|
||||
current tree (Read/Grep). Flag dangling references.
|
||||
4. Cross-check against CLAUDE.md guardrails (single process, CLI-first,
|
||||
own the rendering stack, etc.) — flag tickets that conflict.
|
||||
|
||||
Assess: does an implementer have enough context to proceed without
|
||||
guessing? Report exactly one of:
|
||||
- READY: <one-paragraph summary of what the implementer needs to know>
|
||||
- GAPS: <list of specific ambiguities, each with 2–3 options>"
|
||||
})
|
||||
```
|
||||
|
||||
Run all agents in parallel (single message, multiple Agent tool calls).
|
||||
|
||||
### 2c. Resolve gaps
|
||||
|
||||
For each ticket that came back GAPS, surface ambiguities to the user
|
||||
via AskUserQuestion. After the user resolves, append the resolution to
|
||||
the ticket via pql:
|
||||
|
||||
```bash
|
||||
pql ticket refine write T-NN '{"description":"<existing body>\n\n---\nRefinement: <resolution>"}'
|
||||
```
|
||||
|
||||
If a gap really requires a new D-record (architectural choice, not just
|
||||
detail), flag it. Ask whether to write the D-record now (`pql decisions
|
||||
claim D <domain> "title"` then author the markdown) or defer with a note
|
||||
on the ticket.
|
||||
|
||||
### 2d. Present refined batch summary
|
||||
|
||||
Per ticket:
|
||||
|
||||
- READY summary, or the resolution the user just gave.
|
||||
- Linked D/Q-records.
|
||||
- Remaining blockers (should be none — re-check if Step 1 was a while ago).
|
||||
|
||||
Ask: "Batch ready. Activate?"
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Batch Activation
|
||||
|
||||
### 3a. Mark tickets in_progress
|
||||
|
||||
Batch transition (comma-separated IDs):
|
||||
|
||||
```bash
|
||||
pql ticket status T-1,T-2,T-3 in_progress
|
||||
```
|
||||
|
||||
### 3b. Branch? Default no.
|
||||
|
||||
Solo-dev flow on this repo — work lands directly on `main` (see recent
|
||||
`git log`). Don't create a topic branch unless the user explicitly asks.
|
||||
If they do, plain `git checkout -b` is fine; there is no `gh` CLI.
|
||||
|
||||
### 3c. Spawn implementation agents (optional)
|
||||
|
||||
If the user wants agents driving the work, spawn `general-purpose`
|
||||
subagents (`model: sonnet`) per ticket. Each prompt should include:
|
||||
|
||||
- Ticket details + the refinement summary from Step 2.
|
||||
- The full content of any linked D-record (Read it and inline it — don't
|
||||
just cite the ID; the agent has no project memory of it).
|
||||
- Repo guardrails the work touches (from CLAUDE.md — quote the relevant
|
||||
bullets, don't link).
|
||||
- A RULES block: write files only, no git commits, no destructive ops,
|
||||
message back when blocked or done.
|
||||
|
||||
### 3d. Report
|
||||
|
||||
End with a tight summary:
|
||||
|
||||
- Branch.
|
||||
- Tickets now `in_progress`.
|
||||
- Agents spawned (if any).
|
||||
- Next step: implement, then commit per the [git-commit skill](../git-commit/SKILL.md).
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Don't skip Step 0 — stale `pql.db` makes the rest of the skill lie.
|
||||
- Don't activate a batch the user hasn't confirmed.
|
||||
- Don't spawn refinement agents for tickets that have no description — use
|
||||
`pql ticket refine` instead; it's cheaper and writes back through the
|
||||
proper channel.
|
||||
- Don't reach for `gh` — this system doesn't have it. Plain `git` only.
|
||||
- Don't `cd` into subdirectories — run everything from the repo root.
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"exported_at": "2026-05-06T15:47:52Z",
|
||||
"exported_at": "2026-05-06T15:48:03Z",
|
||||
"decisions": [
|
||||
{
|
||||
"id": "D-1",
|
||||
|
||||
Reference in New Issue
Block a user