Process pending GSD events and sync Jira cards (create/update epics, features, subtasks)
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-gsd-jira-plugin:jira-sync --dry-run | --full | --status--dry-run | --full | --statusclaude-haiku-4-5-20251001This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
<objective>
$ARGUMENTS
Check $ARGUMENTS:
--status -> Show queue stats and exit (step 1 only)--dry-run -> Show what would happen without calling Jira API--full -> Ignore queue, re-scan all .planning/ dirs and sync everythingdata/jira-queue.json -- the pending eventsdata/jira-mapping.json -- existing card-id -> Jira issue key mappingdata/jira-config.json -- transition IDs and project key (if exists)--status: print summary table of pending events grouped by repo and type, then stopJIRA_HOST, JIRA_USERNAME, JIRA_API_TOKENJIRA_PROJECT_KEY env var is set, use itdata/jira-config.json has projectKey, use itGET /rest/api/3/project and pick the first project (or prompt if multiple)data/jira-config.json exists and has transitions, use thoseGET /rest/api/3/issue/{any-issue}/transitions and cache to data/jira-config.jsonAuto-detect repos by globbing src/*/.planning/ directories.
For each match, extract the repo name from the path (e.g., src/my-api/.planning/ -> my-api).
--full mode:Scan all detected repos and build the full card hierarchy:
For each repo discovered in Step 3:
src/{repo}/.planning/ROADMAP.mdsrc/{repo}/.planning/phases/*-PLAN.md and src/{repo}/.planning/milestones/**/*-PLAN.mdsrc/{repo}/.planning/STATE.md -> update status of active phase/milestonesrc/{repo}/.planning/quick/*/ -> create/update Quick Tasks (see the Quick Tasks section below)Process each event in data/jira-queue.json in order:
| Event | Action on Feature | Cascade on all child Subtasks |
|---|---|---|
milestone_created | Create Epic: [{repo}] {version} -- {name} | — |
phase_added | Create Feature: Phase {N}: {name}, link to Epic -> Backlog | — |
plans_created | Create Subtask: {phase}-{plan}: {objective}, link to Feature | — (this IS the subtask creation) |
phase_planning | Transition Feature -> Planejamento | — (no cascade; subtasks stay in Backlog until execution) |
phase_ready | Transition Feature -> Pronto | — |
phase_executing | Transition Feature -> Executando | Transition every Backlog subtask -> Executando |
phase_verifying | Transition Feature -> Verificacao | — (subtasks keep their state until phase result) |
phase_completed | Transition Feature -> Concluido | Transition every non-Concluido subtask -> Concluido |
phase_verified | If status=passed: Feature -> Concluido. If gaps_found: add comment with gaps, stay in Verificacao | If passed: Transition every non-Concluido subtask -> Concluido. If gaps_found: — |
milestone_completed | Transition Epic -> Concluido | — (subtasks already closed via phase_completed/phase_verified) |
quick_task_created | Create Tarefa under the repo [{repo}] Quick Tasks Epic (see Quick Tasks section) | — |
quick_task_completed | Transition the Tarefa -> status from its status: frontmatter (default Concluido) | — |
All transition IDs are read from data/jira-config.json. If the config file is missing, discover transitions via API first (see Step 2).
/gsd-quick)Quick tasks are off-cycle work that has NO milestone/phase parent — they live in src/{repo}/.planning/quick/{slug}/, not in phases/. They are synced as standalone Tarefa issues (the project's non-subtask Task type), grouped under one container Epic per repo so the board doesn't fill with orphans.
Container Epic (one per repo): [{repo}] Quick Tasks — mapping key {repo}/quick, labels [{repoLabel}, gsd-managed, quick]. Create on first quick-task sync for that repo; reuse thereafter.
Each quick task -> one Tarefa:
{repo}/quick/{quick_id} (e.g. core-api/quick/260528-box).Tarefa (NOT Feature — Feature is phase-level; NOT Subtask — there is no parent phase).[{repo}] Quick Tasks Epic.Quick {quick_id}: {slug} (cap ~200 chars).[{repoLabel}, gsd-managed, quick].Two on-disk file conventions exist — handle both:
{dir}/PLAN.md + {dir}/SUMMARY.md, frontmatter quick_id:, slug:, status:.{dir}/{quick_id}-PLAN.md + {quick_id}-SUMMARY.md (+ optional -VERIFICATION.md), frontmatter uses phase:/plan: and usually has NO status:. Derive quick_id from the *-PLAN.md filename prefix (or {dir}/CONTEXT.md task_id:, or the ^\d{6}-\w{2,4} / ^\d{8} dirname prefix). slug = dir basename minus the quick_id prefix.Status resolution (per dir): a terminal artifact wins over a stale PLAN. If a *SUMMARY*.md or *VERIFICATION*.md exists, use its status: (else default complete); otherwise use the PLAN status: (else in-progress). Status -> column map: complete|done|passed|investigated|GO -> Concluido(41), in-progress -> Executando(21), ready -> Pronto(3), planned -> Planejamento(2), issues_found -> Verificacao(31).
Backfill note (2026-06-24): 206 historical quick tasks were retroactively imported (core-api 48, pwa 99, infra 38, backoffice 21) under Epics PIB-887/888/889/890. Idempotent thereafter via the {repo}/quick/{quick_id} mapping keys.
Observed failure in Phase 44 Foundation & Safety (core-api, 2026-04-17): all 7 subtasks stayed in Backlog after the phase shipped, because the original skill only transitioned the Feature. Operators had to transition each subtask manually via Jira MCP.
The cascade pattern above mirrors reality: when a phase enters execution, its plans are being worked on; when a phase is verified passed, its plans are done. Subtasks should reflect the parent Feature's state automatically.
Rules for the cascade:
gsd-managed (do not touch manually-created subtasks).Concluido subtask).When CREATING a card, always include a structured description in Atlassian Document Format (ADF). Extract content from the GSD artifact that triggered the event.
Source: src/{repo}/.planning/ROADMAP.md + milestones/{version}-ROADMAP.md
## Goal
{milestone name/goal from ROADMAP.md}
## Phases
{phase range} -- {done}/{total} complete
- Phase N: Name [done/pending]
...
## Stats
{from MILESTONES.md if available: accomplishments, test counts}
Source: milestones/{version}-ROADMAP.md section ### Phase N:
## Goal
{**Goal**: line from phase section}
## Requirements
- {requirement codes: AUTH-01, etc.}
## Success Criteria
- {numbered criteria from **Success Criteria** block}
## Plans
- {plan list from **Plans**: block}
## Dependencies
{**Depends on**: line}
Source: {phase-dir}/{NN}-{PP}-PLAN.md (YAML frontmatter + tag)
## Objective
{first line of <objective> tag}
## Requirements
- {requirements from frontmatter}
## Must-Haves
- {truths from must_haves.truths}
## Files Modified
- {files_modified list, max 15}
Wave: {wave number}
{
"type": "doc", "version": 1,
"content": [
{"type": "heading", "attrs": {"level": 2}, "content": [{"type": "text", "text": "Goal"}]},
{"type": "paragraph", "content": [{"type": "text", "text": "..."}]},
{"type": "bulletList", "content": [
{"type": "listItem", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "..."}]}]}
]}
]
}
For each card operation, use bash with curl to call Jira REST API v3:
PROJECT_KEY=$(cat data/jira-config.json | jq -r '.projectKey')
curl -s -X POST \
"${JIRA_HOST}/rest/api/3/issue" \
-H "Authorization: Basic $(echo -n '${JIRA_USERNAME}:${JIRA_API_TOKEN}' | base64)" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"project": {"key": "'${PROJECT_KEY}'"},
"summary": "...",
"description": {ADF document from Step 4.5},
"issuetype": {"name": "Epic|Feature|Subtask"},
"labels": ["gsd-managed", "{repo-label}"],
"priority": {"name": "High"}
}
}'
# First get available transitions
curl -s "${JIRA_HOST}/rest/api/3/issue/{key}/transitions" ...
# Then transition using ID from data/jira-config.json
TRANSITION_ID=$(cat data/jira-config.json | jq -r '.transitions.executando')
curl -s -X POST "${JIRA_HOST}/rest/api/3/issue/{key}/transitions" \
-d '{"transition": {"id": "'${TRANSITION_ID}'"}}'
Use the Epic Link field (discover via /rest/api/3/field -- typically customfield_10014).
When processing phase_executing, phase_completed, or phase_verified:passed, list the Feature's subtasks and transition each one:
FEATURE_KEY="PIB-401"
TARGET_TRANSITION=$(cat data/jira-config.json | jq -r '.transitions.concluido.transitionId')
AUTH="$(echo -n "${JIRA_USERNAME}:${JIRA_API_TOKEN}" | base64)"
# JQL: parent=<feature> AND labels=gsd-managed — do not touch manually-created subtasks
SUBTASK_KEYS=$(curl -s -G "${JIRA_HOST}/rest/api/3/search" \
--data-urlencode "jql=parent=${FEATURE_KEY} AND labels=gsd-managed" \
--data-urlencode "fields=status" \
-H "Authorization: Basic ${AUTH}" \
| jq -r '.issues[] | select(.fields.status.name != "Concluido") | .key')
for KEY in ${SUBTASK_KEYS}; do
curl -s -X POST "${JIRA_HOST}/rest/api/3/issue/${KEY}/transitions" \
-H "Authorization: Basic ${AUTH}" \
-H "Content-Type: application/json" \
-d "{\"transition\": {\"id\": \"${TARGET_TRANSITION}\"}}" \
|| echo "WARN: failed to transition ${KEY} (continuing)"
done
Only transition subtasks that are not already in the target state (see Idempotency Rules below).
After each successful create:
data/jira-mapping.json: "{repo}/{milestone}/{phase}/{plan}": "{PROJECT_KEY}-XXX"Remove processed events from data/jira-queue.json. Keep failed events with an error field.
Print summary:
Jira Sync Complete
Created: 2 features, 4 subtasks
Updated: 1 epic (status -> Concluido)
Failed: 0
Remaining in queue: 0
jira-mapping.json -- if card-id exists, UPDATE instead of CREATEgsd-managed -- this identifies managed cards{repo}/{milestone}/{phase}/{plan}
Examples:
my-api/v2.0 -> Epicmy-api/v2.0/32-iam-foundation -> Featuremy-api/v2.0/32-iam-foundation/plan-01 -> SubtaskTransition IDs vary per Jira project. They are stored in data/jira-config.json:
{
"projectKey": "PROJ",
"transitions": {
"backlog": { "transitionId": "11", "statusId": "10000" },
"planejamento": { "transitionId": "2", "statusId": "10036" },
"pronto": { "transitionId": "3", "statusId": "10037" },
"executando": { "transitionId": "21", "statusId": "10001" },
"verificacao": { "transitionId": "31", "statusId": "10002" },
"concluido": { "transitionId": "41", "statusId": "10003" }
}
}
If data/jira-config.json does not exist, discover transitions by calling:
curl -s "${JIRA_HOST}/rest/api/3/issue/{any-issue-key}/transitions" \
-H "Authorization: Basic $(echo -n '${JIRA_USERNAME}:${JIRA_API_TOKEN}' | base64)"
Then save the discovered IDs to data/jira-config.json for future runs.
| Column | Status Name | Flow Direction |
|---|---|---|
| Backlog | Backlog | Start |
| Planejamento | Planejamento | -> |
| Pronto | Pronto | -> |
| Executando | Executando | -> |
| Verificacao | Verificacao | -> |
| Concluido | Concluido | End |
Auto-detected repos get labels derived from their directory name.
All cards also get gsd-managed.
Common mappings (customize in data/jira-config.json repoLabels if needed):
| Repo Directory | Default Label |
|---|---|
| *-api, *-backend, *-server | backend |
| *-pwa, *-web, *-frontend | frontend |
| *-infra, *-terraform, *-iac | infra |
| (other) | directory name |
If the Claude Code session has the Atlassian MCP server loaded and authenticated (mcp__atlassian__* tools available), you can use those tools instead of curl + env vars. This is useful when:
JIRA_HOST / JIRA_USERNAME / JIRA_API_TOKEN env vars are not set.Equivalent MCP calls:
| curl operation | MCP tool |
|---|---|
POST /rest/api/3/issue (create) | mcp__atlassian__createJiraIssue |
PUT /rest/api/3/issue/{key} (edit) | mcp__atlassian__editJiraIssue |
GET /rest/api/3/issue/{key} | mcp__atlassian__getJiraIssue |
POST /rest/api/3/issue/{key}/transitions | mcp__atlassian__transitionJiraIssue |
GET /rest/api/3/issue/{key}/transitions | mcp__atlassian__getTransitionsForJiraIssue |
GET /rest/api/3/search?jql=... | mcp__atlassian__searchJiraIssuesUsingJql |
Cloud ID: the first MCP call should discover the cloud ID once: mcp__atlassian__getAccessibleAtlassianResources returns the site UUID. Cache in data/jira-config.json under cloudId.
Default strategy: prefer curl when env vars are present (no session dependency, scriptable). Fall back to MCP when env vars are missing or curl fails with auth errors. Both paths are idempotent per the rules above.
npx claudepluginhub dumorro/claude-gsd-jira-plugin --plugin claude-gsd-jira-pluginCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.