skills/slice-into-issues/SKILL.md
--- name: slice-into-issues description: Take a PRD (parent GitHub issue OR local prd.json) and slice it into vertical-slice user-story issues that an agent can pull from a Kanban backlog. Defers to /ro:repo-mode for output target — `personal` repos publish each slice as a child GitHub issue referencing the parent via `## Parent\n\n#<N>` with ready-for-agent label; `work` repos write gitignored `.ralph/issues/*.md` so nothing leaks to the work GH/Jira/ADO project. First-run prompt picks the mode
npx skillsauth add RonanCodes/ronan-skills skills/slice-into-issuesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The missing step between a PRD and a Ralph loop. Matt Pocock's workshop makes this an explicit phase: read the PRD, propose what modules to create or change, then break the work into vertical slices that each touch all the layers they need.
Resolution order (highest precedence first):
--target gh|local flag — always wins./ro:repo-mode resolution. Per-repo .claude/repo-mode, then global ~/.claude/repo-mode. If personal → --target gh (publish each slice as a child GH issue). If work → --target local (write to .ralph/issues/*.md, fully gitignored, nothing leaks to the work GH/Jira/ADO project).unset: run the first-run prompt described in /ro:repo-mode § "First-run prompt". Fires once per repo, then never again.gh remote exists → force --target local regardless of mode.Resolver snippet (same 4 lines documented in /ro:repo-mode):
mode=""
[ -f .claude/repo-mode ] && mode="$(tr -d '[:space:]' < .claude/repo-mode)"
[ -z "$mode" ] && [ -f "$HOME/.claude/repo-mode" ] && mode="$(tr -d '[:space:]' < "$HOME/.claude/repo-mode")"
case "$mode" in personal|work) ;; *) mode="unset" ;; esac
The --prd argument:
--prd 798) → treat as a GH issue number; gh issue view 798 --json title,body to load.--prd .ralph/prd.json or --prd docs/prds/foo.md) → load from disk.--target gh, list open issues with ready-for-agent label whose bodies open with ## Problem Statement (the parent shape) and ask the user to pick. If --target local, fall back to the legacy default of .ralph/prd.json or newest in docs/prds/.For each approved slice, in dependency order (blockers first):
gh issue create \
--title "<slice title>" \
--label "kind:slice" \
--label "${LIFECYCLE_LABEL}" \
${MODIFIER_FLAGS} \
--body-file -
Lifecycle label rules (per the canonical label system, the plugin's canon/labels.md):
LIFECYCLE_LABEL=needs-grilling for slices whose ACs are still hand-wavy after the interview. Day-shift will tighten them.LIFECYCLE_LABEL=ready-for-agent.--skip-grill or interactive override): LIFECYCLE_LABEL=ready-for-agent plus needs-grilling-skipped as a modifier so the reviewer double-checks ACs.Modifier flags (MODIFIER_FLAGS) are added when the slice meets the criterion:
--label hitl-likely if the slice touches ORM, schema migrations, billing, OAuth, secret rotation. Reviewer will probably escalate.--label parallel-eligible if the slice is file-disjoint from its siblings (planner-worker fans these out).--label repo-lock if the slice churns lockfiles, schema reset, or top-level config (planner-worker serialises these).--label bug-fix if the slice begins with a failing test that the implementer makes pass.kind:slice is always added. Legacy project synonyms (Sandcastle etc.) still work via --label <name>; --label <name> flag overrides the lifecycle pick.
Body template — Matt Pocock's slice shape:
## Parent
#$PARENT
## What to build
<concise end-to-end description; cover behaviour, not layer-by-layer implementation>
## Acceptance criteria
- [ ] Criterion 1
- [ ] Criterion 2
- [ ] Criterion 3
### Close-the-loop tests (REQUIRED, every story)
- [ ] **Unit:** new pure functions / Zod schemas / DB repo helpers have vitest coverage.
- [ ] **Integration:** any new API route is exercised via vitest with a mocked Nango / D1.
- [ ] **e2e:** ANY user-facing UI route or flow has a Playwright spec that:
- Navigates to the canonical URL a real user would reach (not just the page in isolation).
- Walks the full input-to-completion path (no "page renders" without "completing the form does what it should").
- Asserts redirects land on the right destination (no loops, no 404s).
- [ ] **Live smoke:** the PR description includes a 30-second manual smoke checklist for the reviewer.
## Blocked by
- #$BLOCKER_ISSUE_NUMBER ← or "None - can start immediately"
The ### Close-the-loop tests subsection is non-negotiable. Every slice this skill emits MUST include it verbatim. The lesson behind it is captured at [[close-the-loop-tests-acs]] in the wiki — a user story without an e2e AC is a guaranteed leak (the night-shift swarm only implements what it's asked for; it does not invent tests it wasn't told to write).
On top of the generic close-the-loop block, emit a concrete, named Playwright e2e acceptance criterion for every user-visible slice — the generic clause says "write an e2e test", this names the happy path and the spec file so the worker has nothing to invent.
Decide per slice from its "What to build" text:
User-visible if it mentions any of: a new route, a new component file, a user action verb (tap / click / type / select), an /app/* path, or a drill / interaction type. → Append, inside the ## Acceptance criteria list, this line (filled in for the slice):
- [ ] Playwright e2e: <one-line description of the happy path>. Spec lives at `e2e/<auth-or-public>/<feature>.spec.ts`. Authed specs reach the gated page via the env-gated server-side synthetic-auth shim (`E2E_TEST_AUTH`), so gate on `isTestAuthEnabled()` — the spec `test.skip`s cleanly when the shim is off. See `canon/clerk-agent-e2e.md`.
Server-only / non-UI (cap raise, schema migration, server-fn refactor with no UI surface, seed-only data) → skip the line. Also skip when the PRD flags the slice surface: server (explicit escape hatch — honour it even if the heuristic would otherwise fire).
The heuristic errs on "include e2e": when in doubt, emit the criterion. Only a clear server-only slice or an explicit surface: server flag suppresses it. This is the slicer half of the write-a-prd Definition of Done; the rule's why lives in the ralph SKILL.md lessons-learned section (Lekkertaal PRD #127 retro: 10 stories shipped with no e2e cost a 3-PR retroactive sweep).
The downstream planner (/ro:planner-worker § "Close-the-loop AC gate") parses the issue body for ### Close-the-loop tests. If missing it either refuses to dispatch (default) or auto-injects the boilerplate, controlled by the repo-local .ronan-skills.json flag swarm.missing_test_acs: refuse|inject.
Publishing in dependency order means earlier slices' real issue numbers can be referenced in later slices' Blocked by sections. Capture each created issue number as you go.
After publishing, comment on the parent PRD issue:
gh issue comment $PARENT --body "Sliced into:
- #$SLICE_1 — <title>
- #$SLICE_2 — <title>
..."
Do NOT close or modify the parent PRD issue body.
Hand off to /agentic-e2e-flow gate 5 (build) or invoke /ro:ralph --source github:ready-for-agent directly.
When the PRD or parent issue carries a Claude Design bundle (a "Send to Claude Code" handoff link, an claude.ai/design share link, or an attached bundle), the per-screen spec must be inlined into each redesign slice body, never referenced by URL.
Why: the Claude Design viewer link is an authenticated viewer, not a public tar. The first worker can fetch it (their session is warm via curl | gunzip | tar); every subsequent worker hits HTTP 404/405 and burns budget re-discovering this before falling back to the parent spec. Surfaced by the Lekkertaal ns-20260521T213503 retro (#207 404'd from #203's spec vs #204 which fetched cleanly).
The rule:
/ro:generate-claude-design-prompt § "What to paste back").## Design spec section (the screen's layout, content, states, components, responsive notes — the exact text from the bundle for that screen). A slice that touches one screen carries that screen's spec; a slice spanning screens carries each.## Design spec via ## Parent\n\n#$PARENT — but the spec text still lives in GH, never behind the auth link./ro:generate-claude-design-prompt carries the matching cross-reference note (it produces the design-input issue these specs come from).
A PRD describes what should exist. An agent loop needs to know in what order, in what chunks. Bad slicing breaks Ralph in three ways:
This skill produces slices that avoid all three.
/slice-into-issues [--prd <path>] [--out <dir>] [--max-slices <N>]
Defaults:
--prd: .ralph/prd.json or the most recently modified file in docs/prds/. Asks if neither exists.--out: .ralph/issues/. Created if missing.--max-slices: 12 (keeps the first pass tractable; can re-run for more).Read the PRD. Confirm it contains:
If any are missing, stop and tell the user to run /write-a-prd first.
Before slicing into stories, propose which modules will be created or modified. Favour deep modules (small interface, large behaviour) over shallow ones. The map looks like:
NEW
- services/gamification.ts (deep: points/levels logic, single export)
MODIFIED
- routes/lessons.ts (add award-points call after completion)
- routes/dashboard.tsx (render points + level)
- db/schema/user-stats.ts (add points, level columns)
Present this to the user. Pause for review. The user can edit the map before slicing begins. This is the most important decision in the whole flow; getting the module shape right makes everything downstream easier.
Each story must satisfy:
blocked-by: 002-add-schema).The first slice especially must bring some piece of every layer online so subsequent slices have a working spine to extend.
One markdown file per slice. Filename convention: NNN-<kebab-slug>.md. Frontmatter:
---
id: 001-award-points-on-lesson-complete
status: ready
blocks: []
blocked-by: []
module: services/gamification.ts
slice-type: vertical
size: small | medium | large
---
Body:
# 001: Award points on lesson complete (visible on dashboard)
## User story
When a user completes a lesson, they receive points and see the updated total on their dashboard.
## Acceptance criteria
- [ ] Schema: user_stats table has `points` column (default 0).
- [ ] Service: `awardPoints(userId, amount)` exists in `services/gamification.ts`.
- [ ] Route: lesson-complete handler calls `awardPoints(userId, 10)`.
- [ ] UI: dashboard renders current points total.
- [ ] Test: integration test covers lesson-complete → points-visible round trip.
### Close-the-loop tests (REQUIRED, every story)
- [ ] **Unit:** new pure functions / Zod schemas / DB repo helpers have vitest coverage.
- [ ] **Integration:** any new API route is exercised via vitest with a mocked Nango / D1.
- [ ] **e2e:** ANY user-facing UI route or flow has a Playwright spec that walks the canonical URL, completes the form, and asserts the next-step destination (no loops, no 404s).
- [ ] **Live smoke:** the PR description includes a 30-second manual smoke checklist for the reviewer.
## Notes
- Points amount per lesson is hardcoded to 10 for this slice. Configurability lands in slice 005.
- Use TDD: write the integration test first.
Before writing files, run the smell tests:
If any check fails, stop and surface the issue to the user. Don't write a bad slicing.
Wrote N issue files to .ralph/issues/:
001-award-points-on-lesson-complete.md
002-...
Module map saved to .ralph/module-map.md
First 1-3 stories are tracer-bullet visible: yes
Next step: /ralph --kanban (or /matt-pocock-coding-workflow continues automatically)
--max-slices or split manually.llm-wiki-ai-research:vertical-slices-tracer-bulletsllm-wiki-ai-research:deep-modules-for-aillm-wiki-ai-research:phase-n-ralph-loopllm-wiki-skill-lab:patterns/close-the-loop-tests-acstesting
--- name: linear-pipeline description: The Fable orchestrator for a single dispatched Linear ticket. Holds almost no context itself; it receives `--issue <ID> --detached`, decides the stage sequence, and fans out a sub-agent per stage, passing forward only each stage's artifact (never re-derived, never inlined into its own context). Step zero, before any planning or stage routing, is a boundary triage against `canon/security-boundary.md` (#199): a match tags Ronan Connolly and stops the run, no
development
--- name: in-your-face description: Capture a chat-only answer into a durable artifact (markdown + HTML, PDF when cheap) and launch it automatically so the user cannot miss it. Use when user says "in your face", "don't let me lose this", "save that answer", "make that durable", or right after answering a substantive side question (a recipe, comparison, how-to, or generated prompt) that would otherwise die with the context. category: workflow argument-hint: [--no-open] [--vault <short>] [hint of
tools
One-shot headless OpenAI Codex CLI calls for background/admin AI tasks — summaries, classification, extraction, admin glue. The default engine for anything that runs AI constantly in the background (daemon-driven, per-event), because it bills the flat ChatGPT subscription instead of Claude usage or per-token API spend, and it keeps working while Claude is rate-limited. NEVER for coding — coding stays Claude. Use when a skill or daemon needs a cheap always-on AI call, when the user says "use codex", "ask codex", "codex as backup", or when building a background summarizer/classifier into a listener or loop. Reads auth from ~/.codex/auth.json (ChatGPT account, no API key).
research
Turn a warranty rejection, repair quote, or RMA email into a cited decision brief — legal read (NL/EU consumer law), is the part user-serviceable, live part and new-unit prices, repair-vs-DIY-vs-new economics, before-you-send-it checklist, deadlines. Use when the user pastes or screenshots a repair quote, warranty rejection, "not covered" email, onderzoekskosten fee, or asks "should I repair or replace this".