Specs and change proposals live in the repo; Jira still owns Epics, Stories, and the board. You can do both without maintaining two truths: tie one OpenSpec change folder to one Story, leave tasks.md out of Sub-tasks, and link every ticket to openspec/changes/.... Most organizations will not retire Jira; this split is how you get SDD anyway without duplicate work or broken traceability.

Contents

1. Context & The Core Tension

OpenSpec is a lightweight spec-driven development (SDD) framework where specifications live in the repository alongside code. Each active change is a folder; it normally contains a proposal, a delta to the spec, a tasks.md checklist, and often design.md for nontrivial work:

openspec/
├── specs/                              # Source of truth (current system behavior)
│   └── <domain>/
│       └── spec.md
└── changes/
    └── <change-name>/
        ├── proposal.md                 # Why & what is changing
        ├── design.md                   # Technical approach (optional)
        ├── tasks.md                    # Implementation checklist
        └── specs/
            └── <domain>/
                └── spec.md             # Delta (ADDED / MODIFIED / REMOVED)

Jira, by contrast, uses a flat three-level hierarchy:

Epic
└── Story | Task | Bug          # Peers at the same level
    └── Sub-task

A widely-held misconception is that Jira supports Epic → Story → Task → Sub-taskIt does not. Stories and Tasks are siblings, not parent-child. Any deeper hierarchy (Initiative above Epic, Feature between Epic and Story) requires Jira Premium with Advanced Roadmaps or a marketplace app like Structure or JXL.

The tension: OpenSpec’s natural unit of work is the change folder (a proposal plus its specs, design, and tasks). Jira’s natural unit of work is the issue (Epic, Story, Task). They do not line up 1:1; forcing a match yields double-bookkeeping or a lossy map.

Below are four ways to line them up, when each tends to work, and a workflow that usually survives contact with a real backlog.

2. Anatomy of What You’re Mapping

2.1 OpenSpec artifacts in detail

ArtifactContentGranularity
specs/<domain>/spec.mdLiving requirements for a capability. Uses SHALL/MUST statements with Given/When/Then scenarios.Domain-level, persistent
changes/<name>/proposal.mdWhy this change exists, what’s in scope, rollback planOne change = one concrete feature/modification
changes/<name>/design.mdTechnical decisions, data model changes, risks, sequence diagramsOne change, optional for small work
changes/<name>/tasks.mdCheckboxed implementation list: - [ ] 1.1 Add theme context providerDozens of items per change
changes/<name>/specs/<domain>/spec.mdDelta: what’s being ADDED / MODIFIED / REMOVED in the living specPer-requirement diffs

A delta spec nests scenarios under requirements inside one file. That is roughly the shape of Epic → Story → acceptance criteria, except it stays plain text in git instead of a ticket tree.

2.2 Jira artifacts in detail

Issue TypePurposeTypical duration
EpicLarge goal-driven body of work, usually cross-sprintWeeks to months
StoryUser-facing feature/requirement with clear valueFits in one sprint
TaskNon-user-facing work (infra, refactor, ops)Fits in one sprint
Sub-taskConcrete implementation step under a Story or TaskHours to a day or two
BugDefectVariable

Stories and Tasks are siblings. Sub-tasks are strictly within the same project as their parent. Epics can span projects.

3. Four Mapping Strategies

Strategy A — Change = Epic (1:1 mapping)

The most direct mapping. Each OpenSpec change folder corresponds to one Jira Epic.

OpenSpec change folder        Jira
─────────────────────────     ───────────────────
changes/add-dark-mode/    ──► Epic: "Add dark mode"
  proposal.md             ──► (Epic description)
  specs/ui/spec.md        ──►
    Requirement 1         ──► Story 1
      Scenario A          ──►   (acceptance criterion)
      Scenario B          ──►   (acceptance criterion)
    Requirement 2         ──► Story 2
  tasks.md                ──►
    1.1, 1.2, 1.3         ──►   Sub-tasks under Story 1
    2.1, 2.2              ──►   Sub-tasks under Story 2
  design.md               ──► Attached/linked to Epic

When it fits: Small-to-mid teams with one Jira project per system, where each change is a genuine Epic-sized effort (multi-sprint, multiple requirements).

Problems:

  • Small OpenSpec changes (a single requirement modification) become over-specified Epics with one Story.
  • Jira Sub-tasks are scoped to the same project as the parent — if tasks.md items cross repos or teams, you cannot model them as Sub-tasks cleanly.
  • You maintain requirements in two places: delta spec and Story descriptions. That is the double-bookkeeping trap.

Strategy B — Domain = Epic, Change = Story

Shift everything up one level. The Epic represents the long-lived domain or capability (matching openspec/specs/<domain>/), and each change folder maps to a Story under that Epic.

openspec/specs/auth/spec.md   ──► Epic: "Authentication"
  changes/add-2fa/            ──►   Story: "Add 2FA"
    tasks.md items            ──►     Sub-tasks
  changes/fix-session-expiry/ ──►   Story: "Fix session expiry"
    tasks.md items            ──►     Sub-tasks

When it fits: Product-led teams where “Authentication,” “Payments,” “Notifications” are long-running investment areas with a continuous stream of small changes.

Problems:

  • Epics never close — they’re effectively themes or components. This breaks Jira’s Epic Burndown report, which assumes Epics have a lifecycle.
  • Cross-domain changes (a change that touches auth/ and payments/) need to live under two Epics, which Jira does not support cleanly for a single Story.

Mitigation: Use Jira Components or Labels for the domain, and let Epics remain genuine initiatives. This effectively moves you toward Strategy D.

Strategy C — Initiative → Epic = change (Jira Premium)

Jira Premium and Advanced Roadmaps add a level above Epic, usually Initiative (portfolio or program: a quarter, theme, or release train). Map one OpenSpec change to one Epic under that Initiative; under the Epic, use Stories for big requirements and Sub-tasks for tasks.md steps only if you want a strict ticket mirror. That layer avoids some “Epic” naming clashes from Strategy A, at the cost of license and admin overhead.

Initiative: "Q2 Security Improvements"
├── Epic: Change "add-2fa"            ──► openspec/changes/add-2fa/
│     ├── Story: Requirement 1        ──► delta spec requirement 1
│     └── Story: Requirement 2        ──► delta spec requirement 2
│           └── Sub-task: task 1.1    ──► tasks.md item 1.1
└── Epic: Change "enforce-pw-rotation"

When it fits: Enterprises on Jira Premium that need SAFe-style planning, portfolio visibility, and regulatory traceability.

Problems:

  • Cost and complexity. Advanced Roadmaps is significant overhead.
  • You still need discipline to keep spec deltas and Story descriptions in sync.

Do not mirror the whole tree. Jira is for planning and status; the repo is for the spec and the checklist you actually execute against.

Jira (coordination)OpenSpec (spec and execution)
Epic — business outcome or program sliceGroups several changes; not a single file in the repo
Story or Task — one deliverable, one owner, one cardOne changes/<name>/ folder per ticket, linked from the description. That folder holds proposal.md, optional design.mdtasks.md, and the delta under specs/.../spec.md
Acceptance criteria — short bullets for stakeholdersThe delta spec’s SHALL / MUST and Given / When / Then. If Jira and the spec disagree, trust the spec.
Status, priority, sprint, assignee, estimatesBehavior and the ordered list in tasks.md (do not retype into Sub-tasks)

Mapping rule: A Jira Story/Task is linked to exactly one OpenSpec change folder (via a link in the Story description: Spec: openspec/changes/add-2fa/). The Jira Epic groups related Stories into a business initiative.

Do not mirror tasks.md into Jira Sub-tasks. That checklist is for the agent and for whoever is implementing; copying it into Jira adds board noise, weakens the checklist inside the agent context, and means updating two systems for the same steps.

Jira Epic: "Ship 2FA for all users"           ──► business initiative
├── Story: "User enables 2FA at signup"       ──► links to openspec/changes/add-2fa/
│   Acceptance criteria (brief, user-visible) ──► (detailed scenarios live in spec.md)
├── Story: "Admin enforces 2FA for org"       ──► links to openspec/changes/enforce-2fa-policy/
└── Task: "Add TOTP secret storage column"    ──► links to same change, infra work

When it fits: Most teams. Treat this as the default unless you have a specific reason for A, B, or C.

Why it works: Product can live entirely in Jira. Engineering keeps a single normative spec next to the code. The Story carries intent and delivery tracking; the delta spec carries behavior. Stakeholders usually only need status at Story granularity anyway.

4. How to Break a Spec Down

Whichever strategy you use, decompose work the same way. OpenSpec’s flow is propose → apply (work through tasks.md) → archive, merging the delta into living specs/. Section 6 pairs that lifecycle with Jira transitions; Section 3 only fixes which issue type holds the link to the change folder.

Step 1 — Start with the capability (domain)

A capability is a noun in your system: Authentication, Checkout, Notifications, Reporting. Each one gets a specs/<domain>/spec.md file. In Jira, this is typically a Component, Label, or (under Strategy B) an Epic.

Step 2 — Scope the change

A change is one coherent modification to one or more capabilities. Good test: “Can I describe the change in one sentence that starts with a verb?” — “Add 2FA,” “Deprecate remember-me cookie,” “Migrate sessions to Redis.” If you need “and,” split it.

One change = one changes/<name>/ folder = (under Strategy D) one Jira Story, or (under Strategy A) one Jira Epic.

Step 3 — Enumerate requirements in the delta spec

Each requirement is a SHALL/MUST statement: user-visible behavior lives here. Map requirements to Story acceptance criteria (bullets under one Story) unless the item needs its own planning, status, and owner — then promote it to a Story.

Rule of thumb: if it could ship, test, and demo on its own, give it a Story. If not, keep it as a criterion on the parent Story.

Step 4 — Generate tasks.md

Tasks are technical, granular, and ordered. They are the AI agent’s to-do list. They do NOT map to Jira. They belong in the repo only.

Good task: - [ ] 1.1 Add totp_secret column to users table with migration Bad task: - [ ] Implement 2FA (too vague — this is a Story, not a task) Bad task: - [ ] Add a comma (too granular — this is editing, not a task)

Step 5 — Size check

If a change has more than ~15 tasks or more than ~5 requirements, it’s probably too big. Split it into multiple changes. This keeps the AI agent’s context window tight and the Jira Story sprint-sized.

5. Is Breaking Specs into Jira Tickets Still Good Practice?

Yes — if tickets track delivery, not a second copy of the spec, and granularity stays sane.

Arguments for continuing to use Jira alongside OpenSpec

  1. Non-dev stakeholders. Product, design, QA, support, and leadership already live in Jira. Git is a barrier for many of them. The Story is the contract they read.
  2. Portfolio visibility. Roadmaps, burndown, sprint planning, capacity. Jira does that; OpenSpec does not try to.
  3. Cross-team dependencies. BlocksIs blocked byRelates to link types in Jira are how you coordinate work across teams. OpenSpec has no equivalent.
  4. Compliance and audit. Regulated industries need an auditable trail of “who approved what, when” at the ticket level. Git history alone is often not enough for auditors who expect ticket-level approvals.
  5. Existing org muscle memory. If your org measures delivery in Jira, fighting that is expensive and usually loses.

Arguments against (or at least cautions)

  1. Double-bookkeeping risk. If you mirror every delta requirement as a Story and every task as a Sub-task, you now maintain requirements in two systems. Either one drifts from the other, or developers waste time syncing.
  2. Jira-as-spec. Story descriptions are not where behavior should live long term. OpenSpec only helps if spec.md next to the code stays authoritative.
  3. Granularity mismatch. tasks.md items are often too small for Jira Sub-tasks and too numerous for sprint boards. Forcing them in creates board noise.
  4. Sprint ceremony overhead. SDD works best when the spec/apply/archive loop is tight. Heavy Jira ceremony (pointing, grooming, status meetings for every Sub-task) slows that loop down.

The verdict

Keep Jira as delivery and coordination, not as the spec. Keep normative behavior in the repo and link tickets to it — Strategy D.

This workflow assumes an AI assistant can read the repo and Jira (for example via MCP).

6.1 Starting from a Jira Story

  1. PO creates Epic & Stories in Jira. Business intent, acceptance criteria in user-visible language, priority, sprint assignment.
  2. Developer picks up a Story. Moves it to In Progress (or a custom “Ready for Spec” state).
  3. Developer runs /opsx:propose "<story summary>" with the Jira ticket ID in the prompt. The AI agent reads the Jira ticket via MCP and generates:
    • changes/<change-name>/proposal.md — includes the Jira ticket ID in the header
    • changes/<change-name>/specs/<domain>/spec.md — delta with requirements & scenarios translated from the Story’s acceptance criteria
    • changes/<change-name>/design.md — technical decisions
    • changes/<change-name>/tasks.md — implementation checklist
  4. Developer reviews the proposal. Stop here if the spec is wrong; fixing prose after code exists is expensive.
  5. Developer runs /opsx:apply. The AI works through tasks.md checkbox by checkbox. Optional: automation updates the Jira Story status on first task completion.
  6. Developer runs /opsx:archive. The delta merges into openspec/specs/<domain>/spec.md. The Jira Story transitions to Done. A PR is opened linking back to both.

6.2 Jira field conventions

Add two custom fields (or use existing ones consistently):

  • Spec Path — text field containing the path to the OpenSpec change folder, e.g. openspec/changes/add-2fa/.
  • Spec Status — automation-driven field mirroring OpenSpec state (proposed / in-progress / applied / archived).

In Story descriptions, always include:

Spec: openspec/changes/add-2fa/
Delta: openspec/changes/add-2fa/specs/auth/spec.md

6.3 Status mapping

OpenSpec phaseJira transition
Change folder created, proposal draftedStory → In Progress (or Spec in Review)
Proposal approved, apply startedStory → In Progress / Implementation
All tasks complete, PR openedStory → In Review
Archived, merged into main specStory → Done

6.4 What does NOT go into Jira

  • Individual tasks.md checkboxes
  • Design decisions from design.md (link the file, don’t paste it)
  • Scenario steps (GIVEN/WHEN/THEN) — summarize as acceptance criteria, keep the detail in the spec

6.5 What must always be in Jira

  • The business-facing Epic
  • The Story with concise acceptance criteria
  • A link to the OpenSpec change folder
  • Status, priority, assignee, sprint

7. Anti-Patterns

  1. One Jira Sub-task per tasks.md checkbox. Explodes board noise, double-bookkeeping, no added value.
  2. Jira Story description as source of truth for behavior. Defeats SDD. The spec file must be authoritative.
  3. An Epic for every small change. Breaks Epic Burndown. Use Strategy D’s Story mapping instead.
  4. No link between Jira and the change folder. Auditors and future developers can’t reconstruct why decisions were made.
  5. Requirements written only in Jira, never in spec.md. The AI agent has no durable context and will drift.
  6. Deleting the change folder after archive. OpenSpec moves it to changes/archive/ for a reason — that’s your audit trail.
  7. Over-abstracting with Initiatives. Only valuable if you have genuine portfolio-level investment streams. Otherwise adds ceremony.

8. Tooling for Sync & Automation

Several tools reduce manual sync between OpenSpec and backlog tools:

  • Linear MCP + OpenSpec MCP — Well-trodden combo: agent reads the ticket, writes the change folder, can bump status. Jira can follow the same shape through Atlassian’s MCP server if your org uses that instead of Linear.
  • SpecFact CLI — Bidirectional sync between OpenSpec and GitHub Issues or Azure DevOps. Status mapping is built in. Jira support has been discussed in their roadmap.
  • Atlassian MCP + custom prompts — With Jira MCP connected, a developer can ask the agent: “Read JIRA-1234, draft the OpenSpec change, and update the ticket status when done.” No custom tooling beyond good prompting.
  • Jira Automation rules — Rule: When a comment on a Story matches openspec-status: applied, transition the Story to In Review. Lets the OpenSpec workflow write back without needing code changes on the Jira side.

Reach for the smallest integration that works. Wiring MCP plus two agreed fields often beats buying a sync product you still have to babysit.

9. Worked Example

9.1 The Jira Epic (PO-authored)

Epic JIRA-500: Ship 2FA for all users
Goal: Reduce account takeover incidents by 80%
Target: Q2

Stories:
  JIRA-501 — User enables TOTP at signup
  JIRA-502 — User manages 2FA in account settings
  JIRA-503 — Admin enforces 2FA org-wide

9.2 The Jira Story (PO-authored)

JIRA-501 — User enables TOTP at signup

As a new user
I want to set up an authenticator app during signup
So that my account is protected from day one

Acceptance criteria:
- TOTP setup is offered during signup flow
- User can scan QR code with standard authenticator apps
- User can skip setup but is prompted again on next login
- Recovery codes are generated and shown once

Spec: openspec/changes/add-totp-at-signup/

9.3 The OpenSpec change (dev-authored via AI)

openspec/changes/add-totp-at-signup/
├── proposal.md
│   "Implements JIRA-501. Adds TOTP enrollment to the signup flow.
│    In scope: enrollment UI, secret storage, QR generation, recovery codes.
│    Out of scope: SMS fallback, WebAuthn."
├── design.md
│   "Secrets stored encrypted at rest via KMS. QR generated client-side.
│    Recovery codes are 10 single-use codes, hashed server-side."
├── specs/auth/spec.md  (delta)
│   ## ADDED Requirements
│   ### Requirement: TOTP Enrollment at Signup
│   The system SHALL offer TOTP enrollment during signup.
│   #### Scenario: User scans QR code
│     - GIVEN a new user completing signup
│     - WHEN they choose "Set up 2FA"
│     - THEN a QR code encoding a TOTP secret is displayed
│     - AND a six-digit code entered from an authenticator verifies the secret
│   #### Scenario: User skips enrollment
│     - GIVEN a new user completing signup
│     - WHEN they choose "Skip for now"
│     - THEN the account is created without 2FA
│     - AND a reminder is shown on their next login
└── tasks.md
    - [ ] 1.1 Add totp_secret (encrypted) and recovery_codes columns
    - [ ] 1.2 Implement TOTP secret generator using otpauth library
    - [ ] 1.3 Add /signup/2fa route and QR rendering
    - [ ] 1.4 Verify entered code against secret
    - [ ] 1.5 Generate & hash 10 recovery codes
    - [ ] 1.6 Display recovery codes modal (one-time)
    - [ ] 2.1 Add skip-and-remind logic to login flow
    - [ ] 2.2 Telemetry: 2fa_enrollment_completed / skipped
    - [ ] 3.1 Unit tests for TOTP verification
    - [ ] 3.2 E2E test: full enrollment happy path
    - [ ] 3.3 E2E test: skip-then-prompted-on-next-login

9.4 What the PO sees

Just JIRA-501, its status, the linked PR, and a one-line spec link. They never open the repo unless they want the detail.

9.5 What the dev and the agent see

The full change folder. The agent reads the repo; Jira mostly gets status updates back. Keep it that thin on purpose.

10. Decision Matrix

SituationStrategy
Solo dev / small team, no external stakeholdersSkip Jira; OpenSpec alone is enough
Small-to-mid team with a PO, standard Jira Free/StandardStrategy D — what/how separation
Team using Jira heavily for portfolio reportingStrategy D + Components/Labels for domains
Enterprise on Jira Premium, SAFe adoptersStrategy C — Initiative → Epic = one change (Advanced Roadmaps)
Long-running capability with many small changesStrategy B — Domain as Epic, with caution
Regulated environment with audit requirementsStrategy D + SpecFact or custom sync + approval gates in both systems

11. Summary

  • OpenSpec owns specification and implementation detail. Jira owns delivery and coordination. Different jobs.
  • Default to Strategy D: one Epic per initiative, one Story or Task per change folder, short acceptance criteria that point at the delta spec, tasks.md only in git.
  • Mirroring tasks.md as Sub-tasks buys noise and drift; skip it.
  • Link both ways: Story points at the folder; proposal header cites the ticket.
  • Automate boring status moves (MCP, Jira Automation). Humans should not click through the same transition twice.
  • Behavior: spec wins. “Done, who, when, which sprint”: Jira wins.

SDD and Jira are fine together if behavior stays in the repo and Jira stays thin: who, when, sprint, no pasted tasks.md.

Everything should be made as simple as possible, but not simpler.“-Einstein

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>