jira-lifecycle
Implements STANDARDS rule #5: every Claude-driven workflow that acts on a
related JIRA issue must keep that issue's status and comment trail in
step with the work, so AI throughput and stage-by-stage cycle time are
measurable from JIRA.
This skill transitions an existing issue and adds comments. It never creates
an issue (file the ticket first — rule #1).
The lifecycle
| Lifecycle point |
Move status to |
Comment |
start — Claude begins work on the related issue |
In Progress |
what's being attempted, by which workflow |
update — a meaningful decision / blocker / finding |
(no change) |
the progress update |
pr — a PR was opened |
(no change) |
PR link + summary (what changed, repo/branch, how to verify) |
ci — the change passed CI |
In Review |
CI is green; moving to review |
staging — deployed and tested on Staging |
Testing |
deployed to Staging; testing started |
done — verified on Production |
Closed |
outcome + links to merged PR / release |
Callers invoke the skill once per point as the work reaches it, passing the JIRA
key and the point (start | update | pr | ci | staging | done).
When to use
- A workflow has just started work tied to a JIRA key →
start.
- A workflow hit a meaningful update worth recording →
update.
- A workflow opened a PR for the work →
pr (posts the link only, no status change).
- The change passed CI →
ci.
- The change was deployed and tested on Staging →
staging.
- Work is verified on Production →
done.
- A developer explicitly asks to move/transition the ticket, post the PR link,
or close it.
When NOT to use
- There is no related JIRA issue — nothing to transition; stop silently.
- You need to create an issue — out of scope (use the
jira skill / rule #1).
- The work is unrelated to any tracked ticket (one-off chores).
How to run
Resolve the related JIRA key. Take it from the caller, the branch name,
or the PR. No key → stop silently (nothing to do).
Load the config from policy/jira-lifecycle.yaml: the stages map
(each stage's status name and numeric transition_id), forward_only, and
the lifecycle order. Map the requested point to its stage:
start → in_progress
ci → in_review
staging → in_testing
done → closed
update → no stage (comment only)
pr → no stage (comment only — posts the PR link without transitioning)
Fetch current state with getJiraIssue (status + key). Use it for the
forward-only check and to avoid redundant transitions.
Decide the transition (forward-only). If forward_only is true:
- First, map the issue's current status name to its stage in
order by
matching it against each stages.*.status value. If the current status
does not match any configured stage (e.g. a custom workflow status like
"Blocked" or "Reopened"), treat it as unmapped: skip the transition
entirely, add the comment anyway, and report the status as
"unknown/unmapped — transition skipped". This is the safe fallback; never
guess a position or move the issue based on an unmapped status.
- If the current status maps to a stage that is at or past the target
stage in
order, do not transition — skip straight to the comment.
- Never move an issue backwards. Re-running a point whose status is already
set is a no-op on status.
Transition if needed. If a status change is warranted:
- If the stage's
transition_id is the unset placeholder (__UNSET__) —
e.g. an in_testing stage on a workflow with no such status — skip the
transition, add the comment anyway, and note in your report that the
status was left unchanged (stage unset).
- Otherwise call
getTransitionsForJiraIssue to confirm the configured ID is
currently available, then transitionJiraIssue with that numeric ID. If
the ID isn't offered, report the mismatch rather than guessing a name.
Add the comment via addCommentToJiraIssue, using the shape for the
point (below). For pr, gather PR details with gh pr view --json url,title,headRefName,baseRefName (or take them from the caller). Add a
comment only when there is real signal — don't post empty "still working"
noise.
Report back the key, the resulting status (or "unchanged — already at/past
target" / "unchanged — stage unset"), and whether a comment was added.
Comment shapes
Keep comments short, factual, and machine-skimmable. Do not invent detail you
can't source.
- start
🤖 Work started by Claude (<workflow / skill name>).
Scope: <one line on what's being attempted>.
- update
🤖 Update: <the decision / blocker / finding>.
- pr (the load-bearing one for metrics — always include the link; no status change)
🤖 PR opened: <PR url>
<PR title> — <repo>@<headRef> → <baseRef>
Summary: <what changed, 1–2 lines>.
Verify: <how to verify, if known>.
- ci
🤖 CI passed; moving to In Review.
- staging
🤖 Deployed to Staging; testing started.
- done
🤖 Verified on Production. Merged: <PR url> · Release: <link if any>.
Outcome: <one line>.
Output
JIRA lifecycle [<point>]: <KEY>
Status: <new status> | unchanged — already at/past target | unchanged — stage unset
Comment: added | skipped (no new signal)
Notes
- Idempotent and forward-only. Safe to re-run a point; it won't move the
issue backwards or double-transition.
- Status mapping is org-config, never hardcoded — it lives in
policy/jira-lifecycle.yaml. A stage left unset there is skipped (comment
still added), so this skill works unchanged across JIRA workflows that lack an
In Testing status.
- This skill only transitions status and adds comments on an existing issue.
It does not create issues, edit other fields, or touch Confluence.
Related
policy/jira-lifecycle.yaml — status names + numeric transition IDs per org.
- STANDARDS.md rule #5 — the rule this skill enforces.
- STANDARDS.md rule #1 — every branch/PR references a real JIRA key (the key this
skill transitions).
1---2name: jira-lifecycle3description: Keep a related JIRA issue's status and comment trail in step with AI-driven work so the lifecycle is visible in JIRA metrics. Idempotent, forward-only transitions at each lifecycle point — move to In Progress when work starts, add progress comments for meaningful updates, post the PR link + summary when a PR opens (no status change), move to In Review when CI passes, move to Testing when on Staging, and Closed when verified on Production. Use whenever a Claude workflow acts on a related JIRA key (MOB-1234, SECVULN-99, …) at any of those points, or when a developer asks to "move the ticket to in progress / in review", "post the PR link on the ticket", or "close the ticket". Do NOT use when there is no related JIRA issue, and do NOT use to create issues.4---56# jira-lifecycle78Implements **STANDARDS rule #5**: every Claude-driven workflow that acts on a9related JIRA issue must keep that issue's **status** and **comment trail** in10step with the work, so AI throughput and stage-by-stage cycle time are11measurable from JIRA.1213This skill transitions an **existing** issue and adds comments. It never creates14an issue (file the ticket first — rule #1).1516## The lifecycle1718| Lifecycle point | Move status to | Comment |19|---|---|---|20| `start` — Claude begins work on the related issue | **In Progress** | what's being attempted, by which workflow |21| `update` — a meaningful decision / blocker / finding | *(no change)* | the progress update |22| `pr` — a PR was opened | *(no change)* | PR link + summary (what changed, repo/branch, how to verify) |23| `ci` — the change passed CI | **In Review** | CI is green; moving to review |24| `staging` — deployed and tested on Staging | **Testing** | deployed to Staging; testing started |25| `done` — verified on Production | **Closed** | outcome + links to merged PR / release |2627Callers invoke the skill once per point as the work reaches it, passing the JIRA28key and the point (`start` | `update` | `pr` | `ci` | `staging` | `done`).2930## When to use3132- A workflow has just **started** work tied to a JIRA key → `start`.33- A workflow hit a **meaningful update** worth recording → `update`.34- A workflow **opened a PR** for the work → `pr` (posts the link only, no status change).35- The change **passed CI** → `ci`.36- The change was **deployed and tested on Staging** → `staging`.37- Work is **verified on Production** → `done`.38- A developer explicitly asks to move/transition the ticket, post the PR link,39 or close it.4041## When NOT to use4243- There is **no related JIRA issue** — nothing to transition; stop silently.44- You need to **create** an issue — out of scope (use the `jira` skill / rule #1).45- The work is unrelated to any tracked ticket (one-off chores).4647## How to run48491. **Resolve the related JIRA key.** Take it from the caller, the branch name,50 or the PR. No key → stop silently (nothing to do).51522. **Load the config** from `policy/jira-lifecycle.yaml`: the `stages` map53 (each stage's `status` name and numeric `transition_id`), `forward_only`, and54 the lifecycle `order`. Map the requested point to its stage:55 - `start` → `in_progress`56 - `ci` → `in_review`57 - `staging` → `in_testing`58 - `done` → `closed`59 - `update` → no stage (comment only)60 - `pr` → no stage (comment only — posts the PR link without transitioning)61623. **Fetch current state** with `getJiraIssue` (status + key). Use it for the63 forward-only check and to avoid redundant transitions.64654. **Decide the transition (forward-only).** If `forward_only` is true:66 - First, map the issue's **current status name** to its stage in `order` by67 matching it against each `stages.*.status` value. If the current status68 does **not** match any configured stage (e.g. a custom workflow status like69 "Blocked" or "Reopened"), treat it as **unmapped**: skip the transition70 entirely, add the comment anyway, and report the status as71 "unknown/unmapped — transition skipped". This is the safe fallback; never72 guess a position or move the issue based on an unmapped status.73 - If the current status maps to a stage that is **at or past** the target74 stage in `order`, do **not** transition — skip straight to the comment.75 - Never move an issue backwards. Re-running a point whose status is already76 set is a no-op on status.77785. **Transition if needed.** If a status change is warranted:79 - If the stage's `transition_id` is the unset placeholder (`__UNSET__`) —80 e.g. an `in_testing` stage on a workflow with no such status — **skip the81 transition**, add the comment anyway, and note in your report that the82 status was left unchanged (stage unset).83 - Otherwise call `getTransitionsForJiraIssue` to confirm the configured ID is84 currently available, then `transitionJiraIssue` with that numeric ID. If85 the ID isn't offered, report the mismatch rather than guessing a name.86876. **Add the comment** via `addCommentToJiraIssue`, using the shape for the88 point (below). For `pr`, gather PR details with `gh pr view --json url,title,headRefName,baseRefName` (or take them from the caller). Add a89 comment only when there is real signal — don't post empty "still working"90 noise.91927. **Report back** the key, the resulting status (or "unchanged — already at/past93 target" / "unchanged — stage unset"), and whether a comment was added.9495## Comment shapes9697Keep comments short, factual, and machine-skimmable. Do not invent detail you98can't source.99100- **start**101 ```102 🤖 Work started by Claude (<workflow / skill name>).103 Scope: <one line on what's being attempted>.104 ```105- **update**106 ```107 🤖 Update: <the decision / blocker / finding>.108 ```109- **pr** (the load-bearing one for metrics — always include the link; no status change)110 ```111 🤖 PR opened: <PR url>112 <PR title> — <repo>@<headRef> → <baseRef>113 Summary: <what changed, 1–2 lines>.114 Verify: <how to verify, if known>.115 ```116- **ci**117 ```118 🤖 CI passed; moving to In Review.119 ```120- **staging**121 ```122 🤖 Deployed to Staging; testing started.123 ```124- **done**125 ```126 🤖 Verified on Production. Merged: <PR url> · Release: <link if any>.127 Outcome: <one line>.128 ```129130## Output131132```133JIRA lifecycle [<point>]: <KEY>134 Status: <new status> | unchanged — already at/past target | unchanged — stage unset135 Comment: added | skipped (no new signal)136```137138## Notes139140- **Idempotent and forward-only.** Safe to re-run a point; it won't move the141 issue backwards or double-transition.142- **Status mapping is org-config**, never hardcoded — it lives in143 `policy/jira-lifecycle.yaml`. A stage left unset there is skipped (comment144 still added), so this skill works unchanged across JIRA workflows that lack an145 **In Testing** status.146- This skill **only** transitions status and adds comments on an existing issue.147 It does not create issues, edit other fields, or touch Confluence.148149## Related150151- `policy/jira-lifecycle.yaml` — status names + numeric transition IDs per org.152- STANDARDS.md rule #5 — the rule this skill enforces.153- STANDARDS.md rule #1 — every branch/PR references a real JIRA key (the key this154 skill transitions).