Task Lifecycle — Phase 1: Plan
Phase 1 of the task lifecycle, run by the jira-task-assigner skill.
Triggered once per task, from the main repo checkout — never a linked
worktree, the opposite reading from phases 2 and 3, because this is the skill
that creates the worktrees — and on the default base branch (or on the
production branch, which is accepted only for an emergency hotfix). The
assigner refuses to run on an existing feature//hotfix/ issue branch or
from a detached HEAD (which gives the new branches nothing nameable to be
cut from), and asks the user how to proceed on any other branch.
This phase ends when the assigner reports back: issues exist, branches
and worktrees are ready, a "PR target branch: ... Worktree: ..."
comment is posted on every leaf issue (plus one more on the parent
issue itself in the multistep case) for the next phase to read, and
the report itself is posted as a Jira comment on the parent issue in
addition to the chat reply.
The diagram surfaces the two systems the assigner actually drives as
their own swimlanes — GIT (anything that mutates repo state:
the pre-branch fetch/pull, creating branches, setting
parentbranch config, pushing, adding worktrees) and JIRA
(anything that mutates issue state: creating the top-level or sub-task
issue, posting comments) — so the full interaction reads
User ↔ Assigner ↔ GIT ↔ JIRA left to right. The healthcheck and
get_assignee_email.sh are drawn as self-calls because they gather facts
rather than mutate either system — not because they stay local.
get_assignee_email.sh genuinely only reads .jst/ config, but the
healthcheck also probes both credentials over the network
(GET /myself for Jira, GET /repos/… for GitHub). Both reads, neither a
write.
Sequence diagram
What the diagram shows
- Step labelling — every node carries the step number
jira-task-assigner's ownSKILL.mdgives it, so the diagram and the skill can be read side by side. The assigner numbers Discovery & healthcheck as its step 1; phases 2 and 3 run the same check as an unnumbered pre-step, so their diagrams label itPre-step — Discovery & healthcheckinstead. The step, its name, and thestatuscheck.shcall are identical in all three — only the--roleargument, the rerun-hint override (the assigner and reviewer wrap the call inSTATUSCHECK_RERUN, the executor doesn't) and each skill's own numbering differ, and the diagrams follow the skill rather than renumbering it. - Two preconditions step 1 judges for itself — the
worktreerow never FAILs, andworktrees_dirFAILs only when the path isn't absolute, so the skill decides both rather than the script. The assigner requires the main checkout, stopping on a linked-worktree reading because it creates worktrees rather than running inside one, and it requires<WORKTREES_DIR>to already exist — a missing one reads WARN, and the skill stops to ask rather thanmkdiring it, since the convention may have changed. - Participant routing — the assigner is the orchestrator between
three parties. GIT owns repo state (the pre-branch
fetch/pull --ff-only, branch creation, thebranch.<branch>.parentbranchgit config entry, the push, andgit worktree add). JIRA owns issue state (creating the top-level or sub-task issue — the sub-task carries its parent link — and posting the durablePR target branchcomment). Everything else (the healthcheck, reading the branch context off its rows, investigating the codebase, deciding scope, and resolvingASSIGNEE_EMAIL) stays inside the assigner. - The branch context is read once, by the healthcheck — step 2 judges
the
branchrow step 1 already produced rather than asking GIT again;SKILL.mdsays so explicitly ("the script already rangit branch --show-current; don't re-run it"). The same is true ofget_assignee_email.sh(step 6A), which only reads.jst/config — it makes no Jira call, so it is drawn as a self-call, not a JIRA arrow. - Refresh before branching (step 6) — both paths
git fetch originfirst; only planned work also runsgit pull --ff-only origin <BRANCH_FROM>, because the hotfix path cuts from the freshly fetchedorigin/<PRODUCTION_BRANCH>and a pull there would only move whichever branch happens to be checked out. - Two identities, and they are not the same one — there is no login
step: every Jira call carries
--role assignerand authenticates on that credential per request, so Jira records the assigner as thecreatorandreporterof every issue here — both are derived from the authenticated account, no flag needed. But each issue is assigned to the executor (get_assignee_email.sh→--assigneeon every create, top-level and sub-task), because the executor is who will pick it up — and phase 2 refuses an issue that isn't assigned to it. So the board reads correctly end to end: filed by the assigner, owned by the executor. Both identities come from that role's own required credential pair — there is no default account either can fall back to. Seeplugins/jira-sdlc/skills/_shared/project-config.md. - Investigate + clarify loop — the main place the user is asked
anything by
jira-task-assigner; questions persist until scope, acceptance criteria, and priority are settled, and the answers are then written into the issue description at step 6A.1 rather than left in chat. It is not the only place, though. Five other points can put a question to the user, none of them drawn as this loop: an empty$ARGUMENTS(asked for before anything runs, the healthcheck included), aworktrees_dirrow that read WARN, the branch-context "ask otherwise" path, agit pull --ff-onlythat exits on real divergence at step 6, and the hotfix confirmation below — which carries a sixth of its own, theproduction_branch-unset stop. - The hotfix path has an explicit user gate (step 5C) — the
optafter step 5. The assigner takes it only when the user deliberately asked for an emergency production fix; urgency wording ("urgent", "asap", "blocking") is not that signal, and even on deliberate wording it names the path and waits for a yes before creating anything. A false positive points a PR at production, shipping code that never sat in staging — which is why this is a gate rather than an inference. Theopt's note carries all three of 5C's stop conditions — the gate itself (no yes → create nothing) plus two that fire independently of the answer: a hotfix whoseproduction_branchrow readunset(don't invent the name of the branch you're about to target), and standing on the production branch when the decision turns out to be planned work (continuing would cut tomorrow's feature from production). Two more hotfix-only obligations land later and aren't drawn as nodes: step 6 confirms thePR target branchcomment actually posted (the base resolver's last fallback is<DEFAULT_BASE_BRANCH>, so a hotfix that lost its comment reads as ordinary planned work to a later session), and step 7's report has to say the fix still needs to reach<DEFAULT_BASE_BRANCH>after it lands on production, or the bug returns with the next sprint release. - Scope decision first — the assigner settles scope and the
top-level type (
alt Multistep / else Single-step); inside the multistep loop it provisions each sub-task's issue (JIRA) and then its branch and worktree (GIT) uniformly. - The base decision rides along with scope — planned work (the
default) branches
feature/offdevelopment, while an explicitly requested emergency production fix branches a singlehotfix/offorigin/main(SDLC.md §4). Because it cuts from the fetched remote ref rather than checking production out, the hotfix works the same whether you invoke it fromdevelopmentor frommain—mainis a permitted start state, never a required one, and step 5C stops if it turns out to be planned work. Either way theMultisteparm is always the planned path, and the two never mix within a run. - Provisioning is uniform, with one exception — the push — every
scenario (single-step, multistep parent, sub-task) records
branch.<branch>.parentbranchin git config via GIT and ends with the assigner posting aPR target branch: ... Worktree: ...comment to JIRA for that leaf — the durable source of truth the executor and reviewer will read later. In the multistep case that comment happens once per sub-task and once more on the parent issue after the sub-task loop, so it's neither one-per-leaf nor a single comment overall. The branch is pushed only on the top-level path: step 6A.2 is the assigner's one and onlygit push -u origin, for the single-step issue's branch or the multistep parent's. Step 6C's three actions for a sub-task aregit worktree add -b, theparentbranchconfig, and the comment — no push. A sub-task branch first reaches the remote in phase 2, at the executor's own step 09. The recordedparentbranchvalue differs with it:<BASE_BRANCH>for a top-level branch (never<BRANCH_FROM>— on the hotfix pathghcan targetmainbut notorigin/main), and the parent's branch for a sub-task. - The final report is durable too — before
deactivate Assigner, the report goes to JIRA as a comment on the parent issue in addition to the chat reply to the user, so a later phase (or a fresh session) can recover it without relying on chat history. Its first line is the literalAssignment reportmarker, which is how phase 2's step 4 finds it among the issue's other comments. - Step 8 is the hand-off, and it is a real step — the assigner
deliberately stops short of writing any code, commits, or PRs, and ends
by pointing the user (or one subagent per worktree) at
/jira-sdlc:jira-task-executor, run from inside each worktree with no key argument — optionally with free-form prose notes for that run. Also out of scope here: merging the parent branch back into its own base once the sub-tasks land. That closing note is where phase 2's diagram picks up.