Build a feature plan split into technical stories with Gherkin scenarios in Markdown. Ask whether to deliver to GitHub Issues or Notion, collect required parameters, and after explicit approval create one item per story with parent/blocker relations, aligned labels, and board placement — using GitHub CLI for GitHub or Notion MCP tools for Notion.
Use this skill when the user wants a feature decomposition into implementable technical stories with acceptance scenarios.
Before collecting any other parameters, ask:
Where should the stories be created? Reply
githubfor GitHub Issues ornotionfor a new Notion Kanban board.
Do not proceed until destination is explicitly set to github or notion.
Collect all required parameters before writing the final story set. Ask for exactly one missing parameter at a time.
feature_summary — concise feature scope.epic_id — epic identifier (for example 1).epic_title — epic title.target_category — category/layer (Frontend, Backend, Platform, etc.).story_granularity — expected story size (small, medium, large).labels — preferred label hints (none if no preference).assignee — GitHub login (GitHub) or user email (Notion) (none if not used).milestone — milestone number (GitHub) or sprint name (Notion) (none if not used).parent_relation_mode — how parent linkage is modeled (epic-parent or story-parent).dependency_mode — dependency semantics to apply (blocks / blocked_by).relation_overrides — optional per-story relation overrides (none if not used).repository — target repo in OWNER/REPO format.project_column_id — classic project column ID where cards must be added.notion_parent_page_id — Notion page ID (with or without dashes) of the page where the new Kanban database will be created. Ask the user to share the page URL or ID.project_column_id (GitHub) or notion_parent_page_id (Notion) is unknown, prompt the user to provide it.After all parameters are known, output a Markdown plan with multiple stories. Match this style:
## Story <epic>.<n> — <Story title>
**Epic:** <epic id> - <epic title>
**Category:** <target category>
**Files:** `<file1>`, `<file2>`
**Relations:** Parent: <epic|story-key|none>; Blocks: <story keys|none>; Blocked by: <story keys|none>
**Label intent:** <semantic categories for this story>
---
### Feature: <feature slice name>
> As a <role>, I want <capability> so that <outcome>.
#### Task 1: <task title>
```gherkin
Feature: <task feature name>
Scenario: <scenario title>
Given ...
When ...
Then ...
And ...
```
#### Task 2: <task title>
```gherkin
Feature: <task feature name>
Scenario: <scenario title>
Given ...
When ...
Then ...
```
Rules:
story_granularity.After presenting the stories, stop and ask for explicit approval. Adapt the question to the destination:
GitHub:
Do you approve creating these stories as GitHub issues, applying parent/blocker relations, aligning labels, and adding them to the classic project column now?
Notion:
Do you approve creating a new Kanban database in your Notion page, creating these stories as database pages, and applying parent/blocker relations now?
Do not create issues, pages, relations, labels, or project cards until explicit approval is received.
Uses GitHub CLI and GitHub GraphQL API.
gh label list --repo OWNER/REPO --limit 200
For each story, semantically map label intent to existing labels.
gh label create "<label_name>" --repo OWNER/REPO [--color "<hex_without_hash>"] [--description "<text>"]
gh issue create \
--repo OWNER/REPO \
--title "Story <epic>.<n> — <Story title>" \
--body-file <story_markdown_file> \
[--label "<resolved_label_1>" --label "<resolved_label_2>"] \
[--assignee "<assignee>"] \
[--milestone "<milestone_number>"]
gh api repos/OWNER/REPO/issues/<issue_number> --jq '{id: .id, node_id: .node_id}'
gh api graphql -f query='
mutation($issueId: ID!, $subIssueId: ID!) {
addSubIssue(input: {issueId: $issueId, subIssueId: $subIssueId}) {
issue { id number }
subIssue { id number }
}
}' -F issueId=<PARENT_NODE_ID> -F subIssueId=<CHILD_NODE_ID>
gh api graphql -f query='
mutation($issueId: ID!, $blockingIssueId: ID!) {
addBlockedBy(input: {issueId: $issueId, blockingIssueId: $blockingIssueId}) {
issue { id number }
blockingIssue { id number }
}
}' -F issueId=<BLOCKED_NODE_ID> -F blockingIssueId=<BLOCKER_NODE_ID>
gh api repos/OWNER/REPO/issues/<issue_number> --jq '.id'
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/projects/columns/<project_column_id>/cards \
-f content_id=<issue_id> \
-f content_type=Issue
Uses Notion MCP tools (notion-create-database, notion-create-view, notion-create-pages, notion-update-page).
Use notion-create-database with parent notion_parent_page_id. Title: <epic_title> — Stories.
Initial schema (self-relations added in step 2):
CREATE TABLE (
"Name" TITLE,
"Status" SELECT('To Do':gray, 'In Progress':blue, 'Done':green),
"Category" SELECT('Frontend':orange, 'Backend':purple, 'Platform':pink),
"Labels" MULTI_SELECT(),
"Assignee" PEOPLE,
"Milestone" RICH_TEXT,
"Epic" RICH_TEXT
)
Capture the data_source_id from the response.
Use notion-update-data-source with the resolved data_source_id to add:
"Blocks" — RELATION('<data_source_id>', DUAL 'Blocked By' 'blocked_by')"Parent Story" — RELATION('<data_source_id>', DUAL 'Sub Stories' 'sub_stories')The dual columns Blocked By and Sub Stories are created automatically.
Use notion-create-view:
type: boardname: Kanbanconfigure: GROUP BY "Status"Use notion-create-pages with parent.data_source_id. For each story set:
Name = Story <epic>.<n> — <Story title>Status = To DoCategory = <target_category>Labels = resolved multi-select values matching label intentAssignee = user if providedMilestone = sprint name if providedEpic = <epic_id> - <epic_title>content = story Markdown body (Gherkin tasks)Capture each created page's id and url.
After all pages are created, use notion-update-page to patch each page's relation properties (Blocks, Blocked By, Parent Story, Sub Stories) using the page IDs resolved in step 4, according to dependency_mode, parent_relation_mode, and relation_overrides.