plugins/lisa/skills/jira-write-ticket/SKILL.md
Creates or updates a JIRA ticket following organizational best practices. Enforces description quality (coding assistant / developer / stakeholder sections), Gherkin acceptance criteria, epic parent relationship, explicit link discovery (blocks / is blocked by / relates to / duplicates / clones), remote links (PRs, Confluence, dashboards), labels, components, fix version, priority, story points, and Validation Journey. Rejects thin tickets — use this skill any time a ticket is created or significantly edited.
npx skillsauth add codyswanngt/lisa jira-write-ticketInstall 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.
All Atlassian operations in this skill go through lisa:atlassian-access. Do not call MCP tools or acli directly.
Create or update a JIRA ticket with all required relationships, metadata, and quality gates. Every section below is mandatory. Thin tickets are rejected.
Repository name for scoped comments: basename $(git rev-parse --show-toplevel).
Determine from $ARGUMENTS and context whether this is a CREATE or UPDATE:
/jira-read-ticket <KEY> first to load the full current state before editing. Never overwrite without reading.Resolve the active Atlassian site via lisa:atlassian-access operation: list-sites (the access skill enforces connection match against .lisa.config.json).
Required fields (stop and ask if missing — do not invent values):
| Field | Required For | Notes |
|-------|--------------|-------|
| Project key | CREATE | Resolve from .lisa.config.json (jira.project); ask the human if not configured |
| Issue type | CREATE | Story, Task, Bug, Epic, Spike, Sub-task, Improvement |
| Summary | CREATE, UPDATE | One line, imperative voice, under 100 chars |
| Description | CREATE, UPDATE | Multi-section — see Phase 3 |
| Epic parent | Non-bug, non-epic | Enforced by lisa:jira-verify |
| Priority | CREATE | Default to project default if unstated |
| Acceptance criteria | Story, Task, Bug, Sub-task, Improvement | Gherkin — see Phase 3 |
| Validation Journey | Runtime-behavior changes | Delegate to /jira-add-journey |
| Target backend environment | Runtime-behavior changes | dev / staging / prod; recorded in description (Phase 3). Skip only for doc/config/type-only tickets. |
| Sign-in account / credentials | Tickets that touch authenticated surfaces | Name the account (or source — 1Password item, env var, seeded fixture) and role; recorded in description (Phase 3). Omit when sign-in is not required. |
| Single-repo scope | Bug, Task, Sub-task, Improvement | These leaf work units MUST cover one repo only. If the work crosses repos, split it before creating. Epic / Spike / Story may span repos. |
Optional but recommended: assignee, components, fix versions, labels, sprint, story points, reporter.
Issue-type validity and required custom fields are enforced by lisa:jira-validate-ticket's F1 / F4 gates (which run via lisa:atlassian-access under the hood). If you need to inspect the metadata directly, request a new operation in atlassian-access rather than calling MCP / acli yourself.
The description MUST address three audiences. Reject and rewrite if any are missing.
h2. Context / Business Value
[Why this matters. Stakeholder-facing. Concrete user impact or business outcome.
Link to the originating Slack thread, Notion doc, incident, or customer report.]
h2. Technical Approach
[Developer-facing. Integration points, impacted modules, data model implications,
relevant tradeoffs. Not a full design doc — a pointer for someone picking it up.]
h2. Acceptance Criteria
# Given <precondition>
When <action>
Then <observable outcome>
# Given <precondition>
When <action>
Then <observable outcome>
h2. Out of Scope
[Explicit list of what this ticket does NOT cover. Forces scope discipline.]
h2. Target Backend Environment
[Required when the ticket changes runtime behavior. One of: dev / staging / prod.
This is the environment QA/product reported against and the backend the
implementer points their local stack at during verification before CI/CD.
Backend-only tickets state the deployed env they target. Skip section
entirely for doc-only, config-only, or type-only tickets.]
h2. Sign-in Required
[Include this section ONLY if the work touches authenticated surfaces.
Specify: the account/role to sign in as, where to get the credentials
(1Password item name, env var, seeded fixture), and any MFA/SSO notes.
Omit the section entirely when sign-in is not required — its absence
means "no sign-in needed for this ticket."]
h2. Repository
[Required for Bug / Task / Sub-task / Improvement. Name the single repo this ticket covers.
If the work spans repos, this ticket type is wrong — split into per-repo
Tasks/Subtasks under a parent Story or Epic. Epic / Spike / Story may
list multiple repos.]
h2. Validation Journey
[Delegate to /jira-add-journey if the ticket changes runtime behavior.
Skip only for doc-only, config-only, or type-only tickets.]
Rules:
Before creating or updating, find candidate relationships. Do NOT skip — this is the step agents most often omit.
If the ticket is not a Bug and not an Epic, it MUST have an epic parent:
project = <PROJECT> AND issuetype = Epic AND statusCategory != Done
via lisa:atlassian-access operation: search-issues jql: "<query>". Match on keywords from the summary and description.Relationship discovery is mandatory on every create and every update — never declare "no related work" without doing both searches below and recording their outcomes on the ticket.
Search 1: local git history (catches PRs/commits that touched the same area but were never linked to a ticket):
# Commits mentioning the keyword
git log --all --oneline --grep="<keyword>"
# Commits that touched the relevant paths
git log --all --oneline -- <path-or-glob>
# Recent activity in this area (last 90 days)
git log --since=90.days --oneline -- <path-or-glob>
If the git search surfaces a PR or commit that relates to this work, capture the PR URL — it becomes a remote link (Phase 4c) and may also point to a sibling ticket worth linking.
Search 2: Jira JQL (catches open and recently-closed tickets):
# Open tickets touching the same component
project = <PROJECT> AND component = "<component>" AND statusCategory != Done
# Open tickets with overlapping keywords
project = <PROJECT> AND (summary ~ "<keyword>" OR description ~ "<keyword>") AND statusCategory != Done
# Epic siblings
"Epic Link" = <EPIC-KEY>
# Recent tickets touching the same labels
project = <PROJECT> AND labels in (<labels>) AND updated >= -30d
# Recently closed tickets in the same area (catches duplicates of work just shipped)
project = <PROJECT> AND component = "<component>" AND status = Done AND updated >= -30d
Record the outcome. Add a ## Relationship Search subsection (or a comment if updating an existing ticket) listing the queries you ran and what they returned. If the searches yielded nothing, write that explicitly — "Searched git history for <keywords> and JQL for component=X, label=Y, epic siblings; no related work found." A ticket with zero links and no documented search is rejected.
For each candidate, classify the relationship:
| Link Type | When to Use |
|-----------|-------------|
| blocks | This ticket must ship before the linked ticket can proceed |
| is blocked by | The linked ticket must ship before this one can proceed |
| relates to | Shared context, no ordering constraint |
| duplicates | This ticket already exists — close one as duplicate |
| clones | This ticket was created from the linked one (e.g. per-repo copies) |
Identify and attach:
lisa:tracker-source-artifacts (invoke that skill if you haven't loaded the rules in this session). The short version: enumerate the parent epic's remote links and inherit the ones whose domain matches this ticket's scope (UI → ui-design + ux-flow; backend → data; infra → ops; always inherit reference). Never assume a developer will walk up to the epic to find design context — attach it here.If the ticket was generated from a PRD (by lisa:notion-to-tracker or similar) and the parent epic has no source artifacts, surface that as a smell and ask whether artifacts were missed during extraction before proceeding.
Source precedence rules and cross-axis conflict handling are defined in lisa:tracker-source-artifacts §3 and §4. When a ticket carries both design artifacts and a description, record the precedence explicitly in the ticket description (under Technical Approach or a dedicated ## Source Precedence subsection) so the implementer doesn't silently reconcile conflicts. Cross-axis conflicts go under ## Open Questions as BLOCKER items.
For UI-touching tickets, include the existing-component reuse expectation per lisa:tracker-source-artifacts §7.
If the ticket modifies an existing user-facing surface, a lisa:product-walkthrough should already have been run upstream (by lisa:notion-to-tracker Phase 2b or lisa:jira-create). Inherit its findings under a ## Current Product subsection in the ticket description so the implementer sees what's shipped today before changing it. If the upstream skill skipped the walkthrough but this ticket clearly modifies an existing surface, invoke lisa:product-walkthrough here before proceeding.
Use Jira's web UI or lisa:atlassian-access operation: write-ticket (UPDATE form) to set the Development field / remote links where supported.
Before create/update, verify each field is populated where applicable:
claude-triaged-{repo} is added later by triage, not here)build_ready)build_ready is an optional write-control input (default: omitted). It governs whether a leaf work unit is promoted to the build-ready role on create. It never overrides leaf-only-lifecycle — a container is never promoted regardless of build_ready. Unlike the label-based trackers, JIRA tickets are already created not-ready (in the project's default initial status, e.g. TODO/Backlog); the build-ready role is the configured ready status (jira.workflow.ready, default Ready), reached by an explicit transition.
build_ready: false → current behavior: leave the ticket in the project's default created status. No transition. A human (or build_ready: true) promotes it to the ready status later.build_ready: true → after create, transition the leaf to the resolved ready role so lisa:intake / lisa:jira-build-intake auto-picks it up (see Phase 6 CREATE step). Resolve the role name with the standard pattern (.jira.workflow.ready // Ready, local overrides global). Best-effort: if the transition is unreachable, record it and leave the ticket in its default status rather than failing the write.Before any write, invoke lisa:jira-validate-ticket with the full proposed spec assembled from Phases 2 / 3 / 4 / 5. Pass it as a YAML block per the lisa:jira-validate-ticket schema, including runtime_behavior_change, authenticated_surface, and artifacts_attached flags so the right gates run.
The validator is the single source of truth for what makes a valid ticket. The same gates are used by lisa:notion-to-tracker dry-run, by lisa:jira-verify post-write, and here. Do not re-implement gate logic in this skill — if a gate needs to change, change lisa:jira-validate-ticket so every caller benefits.
If the validator reports FAIL:
lisa:atlassian-access with operation: write-ticket while the validator's verdict is FAIL.If the validator reports PASS, continue to Phase 6.
Before calling lisa:atlassian-access, keep the description in Lisa's normal Markdown/wiki-heading authoring shape; the access layer owns conversion through scripts/markdown-to-adf.mjs and writes ADF to JIRA. This is required because acli stores raw Markdown/wiki text as one literal paragraph when no ADF object is provided. Post-write verification must confirm the live description contains ADF heading nodes for the required sections, not literal ## / h2. text in a paragraph.
lisa:atlassian-access via the Skill tool with operation: write-ticket payload: {...} containing all Phase 2/3/5 fields and the epic parent from Phase 4a (CREATE form — no existing key).lisa:atlassian-access with operation: link from: <K1> to: <K2> type: "<link-type>". Use the exact link-type names supported by the project; surface errors if an unknown type is passed.lisa:atlassian-access operation: write-ticket UPDATE form or whatever remote-link operation is dispatched).lisa:jira-add-journey skill to append the Validation Journey section.build_ready: true and the ticket is a leaf work unit): transition the new ticket to the resolved ready status via lisa:atlassian-access operation: transition key: <K> to: "<ready-status>" (resolve <ready-status> as .jira.workflow.ready // Ready, local overrides global). Skip this step entirely when build_ready is omitted or false, or for any container. If the transition is unreachable, record it and leave the ticket in its default status — do not fail the write.lisa:atlassian-access with operation: write-ticket payload: {key: <K>, ...fields-being-changed}. Do NOT resend fields that weren't in the change set — it blows away history.lisa:atlassian-access operation: link from: <K1> to: <K2> type: "<link-type>". Existing links are not touched unless explicitly removed./jira-read-ticket first, including any existing canonical managed ## Lisa Usage section unless the caller intentionally supplied an updated canonical section. Use the shared usage-accounting serializer/merge path rather than freehand edits to ledger rows.Call the lisa:jira-verify skill on the resulting ticket. lisa:jira-verify fetches the live ticket and runs lisa:jira-validate-ticket against it — same gates as Phase 5.5, but applied to what JIRA actually stored (catches anything dropped or reformatted on write, including Markdown/wiki descriptions that degraded into one literal text paragraph instead of ADF heading nodes). If it reports failures, fix them before returning. Do not report success on a ticket that fails verify.
Post a creation comment via lisa:atlassian-access operation: comment key: <K> body: "..." with:
[{repo}] prefix if the ticket is repo-scopedblocks, is blocked by, relates to) with linksSkip this step only on UPDATE when no material change was made.
## Lisa Usage section on update; never append a second usage
section or silently drop ledger rows.lisa:jira-create) should delegate here rather than invoking lisa:atlassian-access write operations directly.lisa:jira-validate-ticket, NOT in this skill. This skill calls the validator at Phase 5.5 (pre-write) and Phase 7 (via lisa:jira-verify post-write). When a gate needs to change, change it in lisa:jira-validate-ticket — every caller (write path, dry-run path, post-write verify) picks it up automatically.development
Use Expo DOM components to run web code in a webview on native and as-is on web. Migrate web code to native incrementally.
development
Guidelines for upgrading Expo SDK versions and fixing dependency issues
development
Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).
tools
`@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app.