Case Study: Creating Stories in Jira with Claude Code
Recurring Course Assignment — drafting, refining, and publishing 8 stories from an EPIC document
What This Shows
This walkthrough covers a single Claude Code session that created the EPIC and all 8 stories for Recurring Course Assignment in Jira. It demonstrates how accumulated context from prior sessions eliminates re-briefing, and how iterative story drafting catches scope and framing issues before they reach the backlog.
- Inherited context does the briefing — Claude started with full knowledge of the feature design, story formatting rules, and Jira field conventions from prior sessions
- Draft each story, refine, then batch-create — iterate on content first, push to Jira last
- Decisions emerge during drafting — writing stories forces precision that EPIC-level descriptions don't require
Starting Context
Claude Code's persistent memory system carried forward context from multiple prior sessions. No re-briefing was needed — Claude read the EPIC document and memory files, then was ready to write stories immediately.
From memory (prior sessions)
- V1 scope: Active/Inactive model, 5 capabilities, fixed calendar schedule first
- Story creation rules: title prefixes, required fields, description structure, AC content guidelines
- Jira formatting: MCP tool can't produce rich text; use REST API with ADF JSON
- PM workflow phases: Understand → Decide → Illustrate → Specify → Refine
From local files
- Complete EPIC document with feature overview, business case, workflow, decisions, story breakdown, reporting considerations, and interaction with existing LP settings
- Prior design artifacts (13-component design, brainstorm decisions) — superseded but available for reference
Pattern: Memory compounds across sessions.
This session didn't start with "here's the feature, here's how we write stories." Claude already knew the 5-capability model, the AC formatting rules, the Jira field IDs, and the formatting workaround. Each prior session's feedback and corrections were already baked in.
Session Agenda
- Create EPIC in Jira with formatted description
- Create developer context file and attach to EPIC
- Draft and refine all 8 stories
- Batch-create stories in Jira with proper fields
- Update EPIC, context file, and memory with session outcomes
- UI text and mockups (separate session)
Solving the Context Problem
A practical question came up before story writing: how do developers get the design context when using Claude Code on these stories? The PM has read-only repo access, so putting a CLAUDE.md in the codebase wasn't an option.
PM
As a PM, I only have read access to the repo. Can we attach/reference appropriate md files to the epic or story?
Claude
Two practical options: Confluence/Google Docs linked from the EPIC, or attach .md files directly to the Jira EPIC. I'd recommend attaching to the EPIC — keeps context co-located with the work, and developers can pull it via the Jira API.
Claude created a trimmed version of the EPIC document focused on what developers need: data model, Active/Inactive semantics, deep copy requirements, gating constraints, and interaction with existing LP settings. Business case, reporting considerations, and workflow were left out. Each story's Notes section references it: "See Recurring_Course_Assignment_Context.md attached to EPIC ABT-47211."
Pattern: Bridge the PM-to-developer context gap.
The PM writes the EPIC. Developers read the code. A developer-focused context file bridges the gap — trimmed to what matters for implementation, attached where the work is defined, accessible to both humans and Claude Code.
Story Drafting: Decisions Through Precision
Each story was drafted, reviewed, and refined before moving to the next. The drafting process surfaced decisions that the EPIC didn't force — writing ACs requires a level of precision that higher-level documents don't.
Naming: what's actually recurring?
PM
Is "recurring LPs" accurate? Is the LP recurring? Maybe from the learner's point of view it is, since there are potentially new courses.
Claude
You're right. The LP itself isn't recurring — it's the same LP throughout. What recurs are the courses within it. I'd suggest keeping "recurring" in the feature name (customer language) but using something more precise for the internal LP mode field — the defining characteristic is that LP completion is recomputed dynamically.
PM
This is a cloud story. What we show users is in the Web story. For this story, suggest a good framing for the field name — it should accurately reflect what it does.
This led to separating the naming concern: the feature is "Recurring Course Assignment" (marketing), the LP mode field should be something like dynamic_progress (mechanism), and the user-facing label is deferred to the Web story with UI mockups.
Pattern: Story drafting surfaces naming decisions.
The EPIC could say "new LP mode" without committing to a name. The story AC had to be specific — which forced the distinction between feature name, field name, and UI label. Three different names for three different audiences.
Scope: Courses only
PM
Important context to add. For scope, this version should only cover Courses as LP components. LP can also have Flash Drills and Channels. For scope control, let's keep FD and Channel out of it.
This constraint wasn't in the original EPIC. Writing the first story's ACs — "each LP component has an Active or Inactive state" — raised the question: which components? The answer (Courses only) was added to every story, the EPIC, and the developer context file.
A related discovery: Channels don't count toward LP progress because they're open-ended. Flash Drills do. This distinction matters for the dynamic progress calculation and wasn't documented anywhere.
Pattern: Writing ACs forces scope precision.
An EPIC can say "Active/Inactive per component." A story AC has to say which components. This is exactly the kind of scope question that's better to answer during story writing than during development.
Cloud story style: requirements, not implementation
Claude
[Draft included ACs about API endpoints, server-side validation, field exposure on responses, and error rejection for non-Course components]
PM
It seems too technical for how I write ACs. I prefer letting the AC stay high-level for Cloud stories. You do make good points. Put them in Notes or Implementation suggestions, or something.
This established a structural pattern: Cloud story ACs describe what the system does, while an "Implementation considerations" section captures technical suggestions as advisory, not prescriptive. The distinction was saved to memory for future story-writing sessions.
Save-to-commit behavior
Claude
[Draft AC: "When toggling to Active, the system behavior from Cloud Story 2 is triggered (auto-assign, progress recomputation)."]
PM
One note: the cloud action only gets initiated after the user clicks "Save" on the page.
This correction applied to both the Active/Inactive toggle (Web Story 2) and the "Use for next cycle" action (Web Story 3). All state changes are pending until Save. A small clarification, but it matters for implementation and was consistently applied across both stories.
Don't write ACs for existing capabilities
Claude
[Draft AC: "The admin can rename the new Course, review and update its content items, and set it to Active when ready."]
PM
#5 is not new (can rename, review, update) or covered by (set to active) this story.
Renaming and reviewing content already exist. The AC was removed. ACs should only describe new behavior — otherwise they imply work that isn't there, or worse, suggest reimplementing something that already works.
Pattern: Each correction improves all future stories.
The "keep Cloud ACs high-level" feedback, the "Save-to-commit" rule, the "don't AC existing capabilities" correction — each was applied to remaining stories in this session and saved to memory for future sessions. Corrections compound.
Batch Creation in Jira
With all 8 stories drafted and approved, Claude created them in Jira in a batch operation:
-
Create all 8 stories in parallel
Via the MCP Jira tool, with Epic Link set to ABT-47211. All created in a single parallel call.
-
Format all descriptions
A Python script with ADF helper functions batch-updated all 8 descriptions via the REST API. The MCP tool can only produce plain text — headings, bold, numbered lists, and nested sub-items require direct ADF JSON.
-
Set custom fields
Found In (Cloud/Web), Ready to (Groom), and Assigned Team (Learning Team) set via curl. Sprint moved via agile API.
-
Verify
Spot-checked one story to confirm all fields were set correctly. Fixed the Assigned Team field, which was initially missed — it turned out to be a different custom field (
customfield_11404) than the "Team" field (customfield_11100).
The two-step approach (create via MCP, then format via REST API) is a workaround for the MCP tool's plain-text limitation. Claude saved the exact field IDs and option values to memory so future sessions don't need to rediscover them.
Pattern: Draft first, create last.
All 8 stories were drafted and refined before any Jira tickets were created. This meant cross-references used real Jira keys (assigned during batch creation), scope changes rippled through all stories before they were published, and no tickets needed to be updated for drafting-phase corrections.
Session Output
| Output | Key / Location |
| EPIC | ABT-47211 |
| Cloud: Data model | ABT-47212 |
| Cloud: System behavior | ABT-47213 |
| Cloud: "Use for next cycle" | ABT-47214 |
| Web: LP Properties — mode | ABT-47215 |
| Web: Active/Inactive on Manage Collections | ABT-47216 |
| Web: "Use for next cycle" UX | ABT-47217 |
| Web: Learner view | ABT-47218 |
| Cloud/Mobile: Learner view | ABT-47219 |
| Developer context file | Attached to ABT-47211 |
| Updated memory | Jira field IDs, story rules, project state |
Patterns to Reuse
-
Let memory brief
If prior sessions saved context correctly, the current session needs no re-briefing. Claude starts with the feature model, formatting rules, and field conventions already loaded. Invest in saving context at the end of each session.
-
Draft before creating
Write all stories in the conversation first. Refine them iteratively. Create in Jira only after all are approved. This prevents update churn and lets cross-references use real ticket keys.
-
Stories force precision
An EPIC can say "per component." A story AC has to say which components. Writing ACs surfaces scope decisions (Courses only), naming decisions (feature name vs. field name vs. UI label), and behavior rules (pending until Save) that higher-level documents don't require.
-
Separate behavior from implementation
Cloud story ACs describe what the system does. Technical suggestions (server-side validation, API response shape) go in an "Implementation considerations" section — advisory, not prescriptive.
-
Corrections compound
Each piece of feedback in a story session applies to all remaining stories and is saved to memory for future sessions. "Don't AC existing capabilities" was said once and applied everywhere going forward.
-
Bridge PM-to-developer context
A developer context file — trimmed from the EPIC, attached to Jira — bridges the gap between what the PM writes and what developers need. Each story references it. Accessible to both humans and Claude Code.
-
Save the plumbing
Jira field IDs, option values, API workarounds — save these to memory so they're discovered once, not every session. The next story-writing session starts with the exact field-setting procedure ready to go.
-
UI text can wait
When label and placement decisions aren't ready, include a "Proposed text" section with draft ideas and note "use placeholder text to unblock development." Don't block story creation on wording — but don't skip it either.