Files
EVOLV/.claude/skills/prd-to-issues/SKILL.md

170 lines
13 KiB
Markdown
Raw Normal View History

---
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=12 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**
<13 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.