f5d3fe58ec
Forge usage lived in three places (`AGENTS.md`, `docs/agents/issue-tracker.md`, and habit). This moves the how-to-run-`tea` half into a model-invoked skill that fires on any issue/PR task, and reduces `AGENTS.md` to identity plus pointers. - **new** `.claude/skills/gitea/SKILL.md` — command table plus the traps `tea <cmd> --help` will not tell you. - `AGENTS.md` — Forge section is now one line: Gitea not GitHub, `gh` and the `issue://`/`pr://` URIs fail, then pointers to the skill, `docs/agents/issue-tracker.md`, and `docs/agents/triage-labels.md`. - `.claude/skills/implement-tickets/SKILL.md` — pointer split: tracker conventions to the doc, `tea` usage to the skill. Both `docs/agents/` files are untouched; the skill cites them instead of restating them. Facts in the skill are measured against `tea` 0.14.2 on 2026-08-17, not remembered: - `gh` is not installed, so `read issue://71` errors — there is no fallback to add. - **A bare read is a truncated read.** Without `--comments`, `tea issue <n>` drops every comment silently, with no prompt under a non-TTY: issue #123 prints 40 lines bare, 132 with the flag. The skill makes `--comments` mandatory for any read meant to understand a ticket, with `tea issue list --fields index,comments` as the checkable count. - Issues and PRs share one index space; output is rendered boxes so parsing needs `-o json`; `close` takes no `--comment`; labels never auto-create; multi-line bodies need a heredoc; `tea` exposes neither sub-issues nor dependencies. Unmeasured and marked as such: whether `--comments` covers a PR's review-comment stream — no PR in this repo has comments, so `tea pr review-comments <n>` is named without a claim about overlap. Reviewed-on: #126 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
134 lines
5.6 KiB
Markdown
134 lines
5.6 KiB
Markdown
---
|
|
name: implement-tickets
|
|
description: "Orchestrate a batch of tickets: plan the briefs, then hand each ticket to its own implementer subagent in its own worktree."
|
|
disable-model-invocation: true
|
|
---
|
|
|
|
# Implement tickets
|
|
|
|
You are the **orchestrator**. You write briefs, dispatch, land results, and talk
|
|
to the tracker. You do not write the implementation — every line of ticket code
|
|
is written by a `ticket-implementer` subagent in its own git worktree. Reach for
|
|
the editor yourself only for a merge conflict resolution.
|
|
|
|
Ticket source and tracker conventions: `docs/agents/issue-tracker.md`. `tea` usage: skill `gitea`.
|
|
|
|
## 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.
|
|
|
|
## 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. Get the plan approved
|
|
|
|
Present, and stop:
|
|
|
|
- the wave list, and for each ticket: number, title, one-line brief summary,
|
|
the files or areas it will touch, its verification commands
|
|
- every cross-ticket contract, verbatim as it will appear in the briefs
|
|
- anything you had to assume
|
|
|
|
Wait for approval. Apply the user's edits to the plan, do not relitigate them.
|
|
|
|
## 4. Run a wave
|
|
|
|
Per ticket, before dispatch:
|
|
|
|
```bash
|
|
git worktree add ../ticket-<n> -b ticket/<n>-<slug> <base> # base = the branch you are on
|
|
cp .env ../ticket-<n>/ 2>/dev/null # gitignored, worktrees do not get it
|
|
tea issue edit <n> --add-assignees <your gitea username> # tea login list has it
|
|
```
|
|
|
|
Write the brief 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.
|
|
Then dispatch the whole wave in **one** `task` batch, every item on the
|
|
`ticket-implementer` agent. Each dispatch names: the absolute brief path, the
|
|
worktree path, the branch, the base ref, and the report path
|
|
`.scratch/<batch-slug>/t<n>-report.md`.
|
|
|
|
<brief-template>
|
|
|
|
# Ticket #<n> — <title>
|
|
|
|
**Read first.** `tea issue <n> --comments` for this ticket, then the issue it
|
|
refers to — the parent or spec — the same way. The comments carry decisions the
|
|
body never got updated with. This brief stays the requirements; those two reads
|
|
are the intent behind them.
|
|
|
|
**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>
|
|
|
|
## 5. Land the wave
|
|
|
|
The wave is landed when every ticket in it is closed, reverted, or handed back
|
|
to the user. Per returned ticket:
|
|
|
|
| Status | What you do |
|
|
| --- | --- |
|
|
| `DONE` | merge, comment, close |
|
|
| `DONE_WITH_CONCERNS` | merge, comment the concerns, close only if you judge them non-blocking — otherwise leave open and tell the user |
|
|
| `BLOCKED` / `NEEDS_CONTEXT` | supply what is missing and re-dispatch, or hand back to the user with the specifics. Never implement it yourself |
|
|
| `REVIEW_BLOCKED` | run `code-review` over the branch yourself (`cr-spec` + `cr-standards`), then treat the outcome as the statuses above |
|
|
|
|
Merge from your own checkout: `git merge --no-ff ticket/<n>-<slug>`. A textual
|
|
conflict is yours to resolve (`resolving-merge-conflicts`). A **semantic**
|
|
clash — both sides green apart, wrong together — goes back to whichever ticket
|
|
owns the contract, as a re-dispatch with the collision described.
|
|
|
|
Then `tea comment <n> "<the report summary>"`, `tea issue close <n>`, and
|
|
`git worktree remove ../ticket-<n>`. Keep the report file.
|
|
|
|
Only once the whole wave is landed does the next wave start — its briefs may
|
|
need what this one changed.
|
|
|
|
## 6. Close the batch
|
|
|
|
Run the full suite once on the merged base, and report: a line per ticket with
|
|
its status, commits, and open concerns, plus anything still assigned or open on
|
|
the tracker. A red suite after every ticket went green is an interaction bug —
|
|
diagnose it, name the two tickets, and fix it or hand it back with both named.
|