Four workflow skills that take a feature from fuzzy idea to merged code.
Two human-in-the-loop phases (grill-me, prd), one mostly-together (prd-to-issues
files only on explicit 'create'), and one AFK (ship-it).
grill-me TOGETHER pressure-test the idea with hard interview questions
prd TOGETHER synthesize PRD; gaps stay explicit, not papered over
prd-to-issues MOSTLY thin vertical-slice issues with coverage matrix +
per-issue Slice check; self-audits before showing
ship-it AFK shell loop ships each slice end-to-end with one
commit per issue, status streams to terminal,
Ctrl-C-able, survives session close
Vertical-slice principle throughout: every issue cuts end-to-end through every
integration layer (no horizontal "do all the DB work first" issues). The
AFK loop only ships against acceptance criteria already locked in by the PRD
phase — autonomous code never runs against undefined contracts.
ship-it tracker support: gh (GitHub) and tea (Gitea). For this repo, set
SHIP_IT_TRUNK=development to override the main default.
See .claude/skills/README.md for the full how-to and a worked example.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
170 lines
13 KiB
Markdown
170 lines
13 KiB
Markdown
---
|
||
name: prd-to-issues
|
||
description: Break a PRD down into thin vertical-slice issues — each one cuts end-to-end through every integration layer so it can be demoed and tested on its own, instead of integrating layer-by-layer. Designed to follow a /prd session. Drafts inline first; only creates issues in the tracker after explicit user confirmation. Use when the user invokes /prd-to-issues, asks to "turn the PRD into issues", "create tickets", "slice this into stories", or "file these as issues".
|
||
---
|
||
|
||
# PRD → Issues
|
||
|
||
**Mode: MOSTLY TOGETHER.** Drafting and the self-audit can run AFK. But filing issues is visible to teammates, so the create step *always* requires an explicit "create" / "file them" from the user. Drafting and showing the list does not count as approval.
|
||
|
||
You are now a tech lead translating a PRD into a backlog of **thin vertical slices**. The job is to produce issues an engineer can pick up, ship end-to-end, and demo — without coming back to ask "what does this mean", and without waiting for a separate team to finish a horizontal layer first.
|
||
|
||
## Core principle: vertical slices, not layers
|
||
|
||
Every issue must cut through **all** the integration layers the feature touches — even if the slice is laughably narrow on each layer. The first slice is a **walking skeleton**: the thinnest possible path from input to output that exercises every layer, so you discover integration problems on day one instead of week four.
|
||
|
||
What this looks like in practice depends on the stack. Examples:
|
||
|
||
- **Web feature:** schema migration (one column) + service method (one case) + API endpoint (happy path only) + UI element (one button, one state) + one integration test that hits all of it. Not: "issue 1: schema, issue 2: service, issue 3: API, issue 4: UI".
|
||
- **Data pipeline (this repo's style):** sensor/source config + MQTT topic + Node-RED parse function (one measurement) + InfluxDB write + Grafana panel (one chart) — all wired up for a single signal end-to-end. Not: "issue 1: all MQTT topics, issue 2: all parse functions, issue 3: all dashboards".
|
||
- **Infra:** one service + its compose entry + reverse-proxy route + TLS + a smoke-test curl that returns 200 — all in one issue. Not: "issue 1: compose, issue 2: nginx, issue 3: certs".
|
||
|
||
After the walking skeleton, subsequent slices **deepen** one user-visible behavior at a time (next measurement, next edge case, next UI state), still cutting through all layers each time.
|
||
|
||
## Inputs
|
||
|
||
In order of preference:
|
||
1. A PRD already drafted in the current conversation (typical case — the `/prd` skill just ran).
|
||
2. A path the user passed: `/prd-to-issues docs/prd/foo.md`.
|
||
3. If neither, ask once: "Point me at the PRD (path or paste it)."
|
||
|
||
Do not invent a PRD. If there's nothing to work from, stop and ask.
|
||
|
||
## Tracker detection
|
||
|
||
Check the git remote of the current repo to pick the right tool:
|
||
- `github.com` → use `gh issue create` (already on user's allowlist).
|
||
- `gitea.*` or any other Gitea host → use `tea issues create` if available; otherwise prompt the user to file manually or hit the Gitea API with `curl` (requires a token — ask first).
|
||
- No remote / detached → draft only, do not offer to create.
|
||
|
||
Run `git remote get-url origin` to detect. Mention the detected tracker in your draft preamble so the user can correct it.
|
||
|
||
## How to slice it
|
||
|
||
One issue per **demoable end-to-end behavior**. Work through the PRD this way:
|
||
|
||
1. **Identify the layers.** From the PRD, list every integration layer this feature touches (e.g. DB → service → API → UI → tests; or sensor → broker → parser → store → dashboard). Write this list in the draft preamble so the user can sanity-check it.
|
||
2. **Pick the first slice = walking skeleton.** The simplest user-observable behavior that exercises every layer. One signal, one happy path, one button. It should feel embarrassingly small. That's correct.
|
||
3. **Order the rest by depth, not by layer.** Each subsequent slice adds one new user-visible behavior or one new edge case, still cutting through all layers. Examples of "next slice":
|
||
- The same flow for a second input type (second measurement, second user role, second file format).
|
||
- An error case made visible end-to-end (validation error → API 4xx → UI shows it).
|
||
- A non-functional bar made observable end-to-end (add the metric, the alert, and the dashboard tile in one slice).
|
||
4. **Absorb prerequisites into the slice that needs them.** A schema migration, a new dependency, a config change — these ride along inside the first slice that requires them, scoped to *just* what that slice needs. They are not separate "infra issues" filed ahead of time.
|
||
5. **Open Questions from the PRD** → separate **spike** issues, timeboxed (default 1 day), with definition-of-done = "decision documented in [link]". Spikes are the one exception to the vertical-slice rule because they exist to remove unknowns, not to ship behavior.
|
||
6. **Out-of-scope items** → do **not** file. Mention once in the preamble as "explicitly skipped per PRD".
|
||
|
||
Right-size: if a slice would take >3 days of focused work, it's not thin enough — narrow the behavior (one signal instead of three, one happy path instead of all error cases) rather than splitting it horizontally. If you find yourself wanting to write "issue 1: backend, issue 2: frontend", stop and reslice.
|
||
|
||
## Issue format
|
||
|
||
Each issue is:
|
||
|
||
```
|
||
### <number>. <title>
|
||
|
||
**Title:** <imperative, ≤72 chars. Names the end-to-end behavior, not the layer. "Show live flow rate on dashboard for FT-001" not "Add InfluxDB write for flow sensors">
|
||
**Labels:** <comma-separated. Suggest from: slice, spike, infra, docs, blocked, good-first-issue>
|
||
**Depends on:** <issue numbers in this list, or "none". Most slices should be "none" — if everything depends on slice 1, that's a smell that slice 1 is doing too much>
|
||
**Estimate:** <S / M / L — S=½ day, M=1–2 days, L=3 days. Anything >L means reslice thinner, not split horizontally>
|
||
|
||
**Slice — layers touched**
|
||
<One line listing every layer this issue crosses, e.g. `schema → ingest service → API → UI → integration test`. Confirms the slice is actually vertical. If the list has only one layer, this isn't a slice — go back and reframe.>
|
||
|
||
**Context**
|
||
<1–3 sentences. Why this exists, linking back to the PRD section. Don't restate the whole PRD.>
|
||
|
||
**Scope**
|
||
- <bullet of what's in — phrased as behavior, not tasks. "Posting valid form persists row and shows success toast" not "write controller method">
|
||
- <bullet of what's in>
|
||
|
||
**Out of scope**
|
||
- <bullet — call out the next slice that *will* handle the thing you're deferring, so reviewers see it's not forgotten. Skip the block only if there's no real risk of scope creep.>
|
||
|
||
**Acceptance criteria**
|
||
- [ ] <end-to-end testable criterion — observable at the outermost layer. "Hitting POST /x with body Y returns 201 and the new row appears on the dashboard within 5s" beats "row exists in table">
|
||
- [ ] <testable criterion>
|
||
- [ ] <testable criterion>
|
||
|
||
**Slice check** ✓ / ⚠
|
||
<One short block per issue that you fill in yourself before presenting. Walk the layer inventory and mark each layer as covered or deferred. Example:
|
||
- schema: ✓ adds `flow_rate` column
|
||
- ingest service: ✓ parses one MQTT topic
|
||
- API: ✓ GET /sensors/FT-001 returns latest reading
|
||
- UI: ✓ dashboard tile shows value, auto-refresh 5s
|
||
- integration test: ✓ end-to-end happy path
|
||
- alerting: ⚠ deferred to slice #4 (out of scope, by design)
|
||
If any layer from the inventory is neither covered nor explicitly deferred to a named later slice, mark the issue with ⚠ overall and fix it before presenting. The user sees this block — it's the visible proof the slice is complete.>
|
||
|
||
**Notes** (optional)
|
||
<Pointers to files, prior art, gotchas surfaced during /grill-me. Skip if nothing useful.>
|
||
```
|
||
|
||
Quality bar:
|
||
- Acceptance criteria must be checkable by reading them. "Works correctly" is not a criterion; "POST /foo with body X returns 201 and persists row in table Y" is.
|
||
- Title is imperative and specific. "Auth" is bad; "Add JWT validation to /api/v1 middleware" is good.
|
||
- Context links *back* to the PRD ("Implements REQ-3 from PRD §6.1"). Don't re-justify the feature.
|
||
|
||
## Self-audit before presenting
|
||
|
||
After drafting all issues, **before showing them to the user**, run this audit and fix anything that fails. Do not skip it — the audit is the difference between a backlog that actually ships end-to-end and one that papers over gaps.
|
||
|
||
**Per-issue checks:**
|
||
1. Does the `Slice — layers touched` line include every layer from the inventory, or explicitly defer the missing ones to a later, named slice?
|
||
2. Does every layer in the `Slice check` block have a ✓ or a ⚠-with-reason? No silent omissions.
|
||
3. Is at least one acceptance criterion observable at the *outermost* layer (the one a user or operator sees)? If all criteria are internal (DB rows, log lines), the slice isn't actually end-to-end.
|
||
4. Does the title name a behavior, not a layer? Reject "Add InfluxDB write…"; accept "Show flow rate on dashboard…".
|
||
5. Is the slice independently demoable — could you record a 30-second clip showing it work, without depending on a sibling issue?
|
||
|
||
**Whole-PRD coverage check** (build a coverage matrix in your head, then render it in the preamble — see below):
|
||
1. Every functional requirement in the PRD maps to at least one slice that *fully delivers* it (or to a clearly named later slice). No requirement is left half-covered across multiple slices that all defer the last mile.
|
||
2. Every non-functional requirement (perf, security, observability) is anchored to a specific slice — even if it's a small thread inside a larger slice. Don't let NFRs float.
|
||
3. Every PRD Open Question has a spike issue.
|
||
4. Every Out-of-scope item is mentioned once in the preamble — not silently dropped.
|
||
5. The union of all slices' `layers touched` covers the full layer inventory. If a layer never appears, either the feature doesn't need it (and the inventory was wrong — fix it) or you missed a slice.
|
||
|
||
If any check fails, **fix the draft before presenting it**. Don't show the user a draft you know is incomplete and expect them to catch it.
|
||
|
||
After the audit passes, include a short **Coverage matrix** at the top of the draft so the user can verify too:
|
||
|
||
```
|
||
Coverage matrix:
|
||
REQ-1 (functional) → slice #1, #3
|
||
REQ-2 (functional) → slice #2
|
||
NFR p95 < 200ms → slice #2 (perf test)
|
||
NFR observability → slice #1 (metrics + dashboard)
|
||
Open Q: which auth? → spike #S1
|
||
Out of scope: SSO → not filed (per PRD §10)
|
||
|
||
Layer inventory: schema → service → API → UI → tests → metrics
|
||
Layers in slices: schema(#1,#3) service(#1,#2,#3) API(#1,#2,#3) UI(#1,#3) tests(all) metrics(#1)
|
||
```
|
||
|
||
If the matrix surfaces a gap mid-presentation, stop and revise — don't ask the user to accept a known-incomplete backlog.
|
||
|
||
## Flow
|
||
|
||
1. Read the PRD (from chat or file).
|
||
2. Detect the tracker; note it in one line at the top: `Tracker: gitea.wbd-rd.nl/RnD/infra (via tea CLI)` or similar.
|
||
3. Draft the issues (do not present yet).
|
||
4. **Run the self-audit above.** Fix anything that fails. Repeat until clean.
|
||
5. Output the draft: tracker line, layer inventory, coverage matrix, then the numbered issues (each with its inline `Slice check` block), then a "Dependency graph:" block if there are cross-issue blockers.
|
||
6. **Stop.** Ask: "Looks right? Reply 'create' to file them, 'edit N: <change>' to revise a specific issue, or 'skip N' to drop one."
|
||
7. On `create`: file the issues using the detected tracker's CLI, in dependency order so blocker references resolve. After each one, print the issue number and URL. If a command fails, stop and surface the error — do not continue blindly.
|
||
8. After creation, print a final summary: `Filed N issues: #123, #124, …`.
|
||
|
||
## Safety
|
||
|
||
Filing issues is visible to teammates. Never create issues without an explicit "create" / "file them" / "go ahead" from the user — drafting and showing the list does not count as approval. If the user said something ambiguous like "ok" or "looks good", confirm once more before creating.
|
||
|
||
If the tracker requires auth and the credential isn't present (e.g. no `GITEA_TOKEN`, `gh auth status` fails), stop and tell the user what's needed. Don't try to work around it.
|
||
|
||
## What not to do
|
||
|
||
- **Don't slice horizontally.** No "issue 1: database, issue 2: API, issue 3: UI". If your draft looks like a layer cake, reslice.
|
||
- **Don't front-load prerequisites as separate issues.** The migration, the new dependency, the config change ride inside the slice that needs them.
|
||
- Don't file the PRD itself as an issue. The PRD is the source; issues are the work.
|
||
- Don't create a giant "Epic: <feature>" tracking issue unless the user asked for one. Most teams already have milestones or projects for that.
|
||
- Don't pad issues with restated PRD text. Link, don't copy.
|
||
- Don't assign issues, set milestones, or add to projects unless the user told you which. Leave assignment empty.
|
||
- Don't add comments like "Generated from PRD by Claude" to the issue body. The issues stand on their own.
|