faa80c41ea
Adds `.claude/skills/plan-tickets/SKILL.md` and trims `implement-tickets` to dispatch-only, with the matching `.omp/agents/ticket-implementer.md` update. Docs/skills only — no backend, userscript, or web changes. Reviewed-on: #162 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
126 lines
5.1 KiB
Markdown
126 lines
5.1 KiB
Markdown
---
|
|
name: plan-tickets
|
|
description: "Plan a batch of tickets and write the briefs for its next wave: read the tracker, decide waves and contracts, get the plan approved."
|
|
disable-model-invocation: true
|
|
---
|
|
|
|
# Plan tickets
|
|
|
|
You produce the two artifacts the `implement-tickets` skill runs on: a **plan
|
|
file** and one **brief** per ticket in the next wave. You write no ticket code
|
|
and create no worktrees — that is the runner's half.
|
|
|
|
Ticket source and tracker conventions: `docs/agents/issue-tracker.md`. `tea` usage: skill `gitea`.
|
|
|
|
Called twice in a batch's life, at least: once to open it, then again after each
|
|
wave lands, because a later wave's briefs may need what the last one changed. On
|
|
a re-entry, read the existing `.scratch/<batch-slug>/plan.md` first and plan only
|
|
the next unlanded wave — the waves and contracts already approved there stand
|
|
unless the landed wave proved one wrong.
|
|
|
|
## 1. Collect the tickets
|
|
|
|
The user's argument is the selector: issue numbers, a label, a parent issue, or
|
|
nothing. With nothing, take the open issues labelled `ready-for-agent`.
|
|
|
|
Fetch each with `tea issue <n> --comments`, and read the **whole** body —
|
|
acceptance criteria and the `Blocked by` line are what the rest of this skill
|
|
runs on. A ticket whose blockers are still open is out of this batch unless a
|
|
blocker is also in it. Read the issue each ticket refers to, its parent or spec,
|
|
the same way: nothing on the implementation path reads the tracker after you —
|
|
only `cr-spec` does, at review time — so a decision that lives in a comment
|
|
reaches the implementer only if you carry it into the brief.
|
|
|
|
## 2. Plan the batch
|
|
|
|
Explore enough of the codebase to write briefs a fresh context can act on: the
|
|
files each ticket lands in, the patterns it must follow, the `AGENTS.md`
|
|
invariants it touches.
|
|
|
|
Then decide three things:
|
|
|
|
- **Waves.** Blocking edges set the order; tickets with no open blocker inside
|
|
the batch share a wave. Cap each wave at **3** concurrent tickets unless the
|
|
user set another width.
|
|
- **Contracts.** Two tickets in one wave that meet at a function signature, a
|
|
JSON shape, a table column, or a token name: you decide the shape now and
|
|
write the identical wording into both briefs. A contract left for the
|
|
subagents to negotiate is a merge conflict you scheduled.
|
|
- **Splits.** A ticket too big for one fresh context window goes into the wave
|
|
as two briefs, or back to the user.
|
|
|
|
## 3. Write the artifacts
|
|
|
|
Pick a `<batch-slug>` — short, from what the batch is about — and write
|
|
`.scratch/<batch-slug>/plan.md`. It is the handoff: the runner is a fresh context
|
|
that reads this and nothing of your reasoning.
|
|
|
|
<plan-template>
|
|
|
|
# Batch <batch-slug>
|
|
|
|
**Base branch.** The branch every worktree forks from and merges back into.
|
|
|
|
**Waves.** A table: wave number, ticket number, title, brief path, and status —
|
|
`planned` | `dispatched` | `landed` | `handed back`. Every ticket in the batch,
|
|
including waves not briefed yet.
|
|
|
|
**Contracts.** Each cross-ticket contract verbatim, naming both ticket numbers.
|
|
|
|
**Assumptions.** What you had to assume, and what the user corrected at approval.
|
|
|
|
</plan-template>
|
|
|
|
Then write a brief per ticket in the next wave to
|
|
`.scratch/<batch-slug>/t<n>-brief.md`, using the template below, in the
|
|
ubiquitous language of `CONTEXT.md` — a brief that says "scrape" where the domain
|
|
says Poll hands the subagent the wrong model of the system.
|
|
|
|
<brief-template>
|
|
|
|
# Ticket #<n> — <title>
|
|
|
|
**Decisions.** Whatever the ticket's comments or its parent spec settled that
|
|
the body never got updated with, restated verbatim. The implementer reads this
|
|
brief and the code, never the tracker — a decision missing here is lost to it,
|
|
and a stale comment thread is not a source you want a fresh context guessing
|
|
from. Omit only when the ticket has no comments.
|
|
|
|
**Goal.** The end-to-end behaviour this ticket makes work, from the user's side.
|
|
|
|
**Acceptance criteria.** Verbatim from the ticket.
|
|
|
|
**Contract.** The exact shared signatures / shapes / names this ticket must
|
|
implement or consume, and which sibling ticket is on the other end. Omit when
|
|
the ticket touches nothing shared.
|
|
|
|
**Where it lands.** The files and packages, and the existing pattern to follow
|
|
in each.
|
|
|
|
**Binding invariants.** The `AGENTS.md` rules this change can break — name them.
|
|
|
|
**TDD seams.** Where a test comes first — run the `tdd` skill at each one and
|
|
follow its red → green loop. Or "none — verify after".
|
|
|
|
**Verify.** The exact commands, e.g. `cd backend && go test ./...`,
|
|
`node --test userscript/test/logic.test.js`.
|
|
|
|
**Out of scope.** What not to touch, especially a sibling ticket's files.
|
|
|
|
</brief-template>
|
|
|
|
## 4. Get the plan approved
|
|
|
|
Present, and stop:
|
|
|
|
- the wave list, and for each ticket in the next wave: number, title, one-line
|
|
brief summary, the files or areas it will touch, its verification commands
|
|
- every cross-ticket contract, verbatim as it appears in the briefs
|
|
- anything you had to assume
|
|
|
|
Wait for approval. Apply the user's edits to the plan, do not relitigate them —
|
|
into the files, not just the reply, or the runner never sees them.
|
|
|
|
Then hand off: name the batch slug and the wave, and stop. Running the wave is
|
|
`implement-tickets`.
|