| name | jira-build-intake |
| description | Symmetric counterpart to notion-prd-intake on the JIRA side. Scans a JIRA project (or JQL filter) for tickets in the configured `ready` status, claims the first eligible ticket by transitioning to the configured `claimed` status, runs the implementation/build flow via jira-agent, transitions to the configured `done` status on completion, then exits. Enforces the claim-time arm of the `leaf-only-lifecycle` rule: a parent/container with open child work (or a childless Epic) that still carries a stale build-ready status is skipped or safe-blocked with a lifecycle-repair comment, never claimed. The `ready` status is the human-flipped signal that a TODO ticket is truly ready for development — mirroring how Notion PRDs work product Draft → Ready → (us) In Review → Blocked|Ticketed. |
| allowed-tools | ["Skill","Bash"] |
JIRA Build Intake: $ARGUMENTS
All Atlassian operations in this skill go through lisa:atlassian-access. Do not call MCP tools or acli directly.
$ARGUMENTS is one of:
- A JIRA project key (e.g.
SE) — scans that project for tickets in the configured ready status.
- A full JQL filter (e.g.
project = SE AND component = "frontend" AND Status = Ready) — used as-is. The skill will not append a Status = <ready> clause if the JQL already names a status, so callers can intentionally widen.
Run one build-intake cycle. The first eligible ready ticket is claimed, built via the lisa:jira-agent flow, transitioned to the configured done status (env-aware — see below), then the cycle exits. Remaining ready tickets stay queued for later scheduler invocations.
Workflow resolution
Status names are read from .lisa.config.json jira.workflow.*, falling back to defaults documented in the config-resolution rule. Bash pattern:
read_role() {
local role="$1" default="$2"
local local_v global_v
local_v=$(jq -r ".jira.workflow.${role} // empty" .lisa.config.local.json 2>/dev/null)
global_v=$(jq -r ".jira.workflow.${role} // empty" .lisa.config.json 2>/dev/null)
echo "${local_v:-${global_v:-$default}}"
}
READY=$(read_role ready "Ready")
CLAIMED=$(read_role claimed "In Progress")
For env-keyed done, resolve the env first, then look up done[<env>]:
- Explicit caller arg (
target_env=staging) wins.
- Otherwise, infer the env from the PR's base branch via
deploy.branches (reverse lookup: if base is staging, env is staging).
- If
done in config is a string (not a map), use it directly regardless of env.
- If
done is a map and env cannot be resolved, fail loudly — do not pick arbitrarily.
TARGET_ENV="${target_env:-}"
if [ -z "$TARGET_ENV" ] && [ -n "$PR_BASE_BRANCH" ]; then
TARGET_ENV=$(jq -r --arg b "$PR_BASE_BRANCH" \
'.deploy.branches // {} | to_entries[] | select(.value == $b) | .key' \
.lisa.config.json 2>/dev/null | head -1)
fi
DONE_RAW=$(jq -r '.jira.workflow.done // empty' .lisa.config.json 2>/dev/null)
DONE_TYPE=$(jq -r '.jira.workflow.done | type' .lisa.config.json 2>/dev/null)
if [ "$DONE_TYPE" = "string" ]; then
DONE="$DONE_RAW"
elif [ "$DONE_TYPE" = "object" ]; then
[ -z "$TARGET_ENV" ] && { echo "ERROR: jira.workflow.done is env-keyed but env not resolvable"; exit 1; }
DONE=$(jq -r --arg e "$TARGET_ENV" '.jira.workflow.done[$e] // empty' .lisa.config.json)
[ -z "$DONE" ] && { echo "ERROR: jira.workflow.done has no entry for env '$TARGET_ENV'"; exit 1; }
else
case "$TARGET_ENV" in
dev) DONE="On Dev" ;;
staging) DONE="On Stg" ;;
production) DONE="Done" ;;
*) echo "ERROR: cannot resolve done status without env"; exit 1 ;;
esac
fi
Run one build-intake cycle. The first eligible ticket in $READY is claimed by transitioning to $CLAIMED, built via the lisa:jira-agent flow, transitioned to $DONE on completion, then the cycle exits.
Confirmation policy
Do NOT ask the caller whether to proceed. Once invoked with a project key or JQL, run the cycle to completion — claim and dispatch the first eligible ticket through lisa:jira-agent, transition a successful build to $DONE, write the summary, and exit. The caller (a human or a cron) has already authorized the run by invoking the skill; re-prompting defeats the purpose of a background queue.
Specifically forbidden:
- Previewing projected scope (ticket count, projected PR count, build duration) and asking whether to continue.
- Offering A/B/C-style choices like "proceed / skip a few / dry-run only" — the documented behavior IS the default.
- Pausing because the queue is large, tickets look complex, or tickets are likely to be
Blocked by lisa:jira-agent's pre-flight gate. The pre-flight Blocked outcome is a valid terminal state of the per-ticket lifecycle (owned by lisa:jira-agent), not a failure mode — surfacing those tickets to humans is success.
- Pausing because the build flow looks expensive. The cost of one cycle is bounded; the cost of stalling a scheduled cron waiting on a human is unbounded.
The only legitimate reasons to stop early:
- Missing project key / JQL or required configuration. Surface the missing value and exit.
- Workflow misconfigured (pre-flight check finds
$CLAIMED or $DONE not reachable, or $READY status absent). Surface and exit.
- Empty ready set. Exit cleanly with
"No tickets with Status=$READY. Nothing to do."
Lifecycle assumed
The JIRA workflow has these statuses (configured per project — see Workflow resolution above for how role names map to actual workflow values):
TODO → ready → claimed → done(env-keyed) → On QA → archive
(PM/ (us claim) (us done; (downstream)
human) PR ready)
This skill ONLY transitions $READY → $CLAIMED on claim, and $CLAIMED → $DONE on completion. It never touches TODO, post-done statuses, or any blocked/closed states.
Pre-flight check: at start of each cycle, attempt the $CLAIMED and $DONE transitions against a sample ready ticket via lisa:atlassian-access operation: transition key: <K> to: "<status>" (in a probe / dry-run sense — or fetch transition metadata if the access skill exposes that). If the transitions are unreachable, stop and report the workflow misconfiguration to the caller — do not invent transitions.
Phases
Phase 1 — Resolve the query
- Parse
$ARGUMENTS:
- Project key: build JQL
project = <KEY> AND Status = "$READY" ORDER BY priority DESC, created ASC.
- Full JQL: use as-is. If it does not include a
Status clause, append AND Status = "$READY".
- Confirm the configured Atlassian site by invoking
lisa:atlassian-access operation: list-sites (it enforces connection match against .lisa.config.json).
Phase 2 — Find ready tickets
Invoke lisa:atlassian-access operation: search-issues jql: "<JQL>". Capture each ticket's: key, summary, issue type, priority, assignee, parent (epic), labels, components.
If empty, report "No tickets with Status=$READY. Nothing to do." and exit. This is the common idle case.
Phase 3 — Process the first eligible ready ticket
3a.0 Repo-scope gate (claim only current-repo tickets)
A JIRA project can oversee multiple repos (frontend / backend / infrastructure). This skill claims only tickets for the repo it is running in. Run this gate before the leaf-only gate (3a) and the claim (3b), per the repo-scope-split rule's "Claim-time repo scoping" section (cite it by slug; do not restate its decision table).
- Resolve the current repo per
config-resolution "Repo scoping" (.repo → .github.repo → git remote get-url origin basename). If unresolvable, stop and report — do not claim tickets you cannot scope.
- Cheap path first. Prefer candidates already carrying
repo:<current> — a JIRA label, or a component equal to the repo name (accepted as an alias). Keep the Phase 2 scan broad (it must still see unlabeled tickets so they can be determined and stamped); this gate orders/filters the results.
- Per candidate, apply the repo-scope decision (
repo-scope-split):
- Carries
repo:<other> (label or component) → skip (leave it ready for that repo's own intake); next candidate.
- Unlabeled → determine the target repo(s) from the ticket (description, AC, technical approach) confirmed against the code surfaces, then stamp
repo:<name> via lisa:atlassian-access operation: write-ticket (add the label / set the component) so later cycles filter cheaply; re-apply with the now-known repo.
- Multi-repo leaf → split, never claim. Run the
repo-scope-split work-time procedure to break it into single-repo siblings, each created build-ready (build_ready: true) and stamped with its own repo:<name>; the current repo's sibling becomes a normal candidate.
- Single-repo leaf for the current repo → fall through to 3a (leaf-only gate) and 3b (claim).
- Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the ready set is exhausted — exit cleanly with
"No ready tickets for repo <current>. Nothing to do.".
3a. Leaf-only claim gate (skip / safe-block containers)
Build intake claims only independently implementable leaf work units. This enforces the claim-time arm of the vendor-neutral leaf-only-lifecycle rule: a parent/container that still carries a stale build-ready status (e.g. Ready applied before this rule existed, or hand-applied to an Epic/Story) is never claimed — intake skips it or safe-blocks it with a clear lifecycle-repair message. It is the claim-time complement to the write-time labeling in lisa:jira-write-ticket and the validate-time S15 gate in lisa:jira-validate-ticket; all three cite the same rule so the classification never drifts. Never silently implement a container.
Run this gate before the claim transition, starting with the oldest/highest-priority ready candidate. Do NOT transition, comment "Claimed", or invoke lisa:jira-agent for a ticket that fails the gate.
Resolve container vs. leaf — structural first, then nominal. Per leaf-only-lifecycle the classification is structural: a ticket is a container if it has open child work, whatever its declared type; otherwise the issue type decides. Resolve child work using the same hierarchy lisa:jira-read-ticket uses — JIRA's native Epic → Story → Sub-task parentage (Epic link / parent field for Stories under an Epic, and the subtask relationship for Sub-tasks under a Story/Task). Issue links (blocks / is blocked by) express cross-item dependencies and are not parentage — do not count them as children.
Fetch the ticket's children via lisa:atlassian-access operation: search-issues with a JQL that resolves both subtasks and Epic-linked Stories, then count those still open (not in a resolved/Done status):
CHILDREN_JQL='(parent = "<TICKET>" OR "Epic Link" = "<TICKET>")'
OPEN_CHILDREN_JQL="${CHILDREN_JQL} AND statusCategory != Done"
Invoke lisa:atlassian-access operation: search-issues jql: "<OPEN_CHILDREN_JQL>" and let OPEN_CHILDREN be the count of returned issues (0 if none). If the JQL cannot resolve the Epic Link field on this instance (older JIRA / team-managed projects expose parentage differently), fall back to the parentage lisa:jira-read-ticket derives and treat the ticket as a container if any derived child is open. Note "Epic Link unavailable — parentage derived" so the operator knows how children were resolved.
Classify and act (first match wins). The issue type comes from the ticket's issuetype field (Epic, Story, Spike, Bug, Task, Sub-task, Improvement):
| Condition | Class | Action |
|---|
OPEN_CHILDREN > 0 (open child work, any type) | Container | Skip / safe-block — do NOT claim |
| no open children AND type = Epic | Childless Epic (pure rollup container) | Skip / safe-block — do NOT claim |
| no open children AND type ≠ Epic (Bug, Task, Sub-task, Improvement, Story, Spike, or no recognized type) | Leaf work unit | Proceed to 3b claim |
The childless-parent exception promotes every childless type except Epic to a claimable leaf: a childless Story is a directly shippable increment and a childless Spike is the investigation unit, so neither is stranded. Only a childless Epic stays unclaimed — an Epic is a pure rollup container by design, and a childless one is an incomplete decomposition or a mis-applied role, never an implementable unit.
Safe-block (default action for a flagged container). Leave the build-ready status in place (don't silently transition it away — that hides the lifecycle error), post a single lifecycle-repair comment, record the ticket under "Skipped (container)" in the summary, and end the cycle. Do NOT transition to $CLAIMED. Keep the comment idempotent — skip posting if an identical [claude-build-intake] lifecycle-repair comment already exists on the ticket, so a re-entrant cycle doesn't spam it.
Post via lisa:atlassian-access operation: comment key: <TICKET> body: "<message>" with:
[claude-build-intake] Not claimed: this ticket carries the build-ready status ($READY) but is a container with open child work (or a childless Epic), which violates the leaf-only-lifecycle rule. Build-ready (status:ready) is leaf-only per leaf-only-lifecycle — an agent claims and implements leaves, never a container. Repair: move $READY off this parent onto its leaf children (or, for a childless Epic, decompose it into leaf children or reclassify it to a leaf type). A parent's lifecycle state rolls up from its children and is never set to ready directly.
This gate never blocks a legitimate flat Task/Bug: those have no open children and a leaf type, so they fall straight through to the claim in 3b.
3b. Claim
Transition the ticket from $READY to $CLAIMED by invoking lisa:atlassian-access operation: transition key: <TICKET> to: "$CLAIMED".
- Assign to the authenticated user when the ticket is unassigned. A claim must be attributable. If the ticket has no assignee, assign it to the authenticated account — prefer acli
--assignee @me (resolves server-side to the authenticated user, which avoids the federated-accountId mis-assignment), or write-ticket with the accountId from the /rest/api/3/myself identity probe the access skill already documents. Leave an already-assigned ticket's assignee untouched — never reassign work that already has an owner.
- Post a
[claude-build-intake] comment via lisa:atlassian-access operation: comment key: <TICKET> body: "Claimed by Claude. Starting build."
- This is the idempotency lock — a re-entrant cycle's
Status = $READY filter will not see this ticket again.
If the transition fails (permission, missing transition, race), log under "Errors" in the cycle summary and skip this ticket. Do not invoke the build flow on a ticket you didn't successfully claim.
3c. Run the build flow
Invoke the lisa:jira-agent (existing per-ticket lifecycle agent) with the ticket key. lisa:jira-agent owns:
- Reading the full ticket graph (
lisa:jira-read-ticket)
- Running its own pre-flight quality gate (
lisa:jira-verify)
- Running ticket triage (
lisa:ticket-triage)
- Routing to the appropriate flow (Build / Fix / Investigate / Improve based on type)
- Posting progress comments via
lisa:jira-sync
- Posting evidence via
lisa:jira-evidence
Wait for lisa:jira-agent to return. Capture its outcome:
- Success — the build flow completed and a PR exists; evidence posted. The PR may already be merged or still open (auto-merge enabled, awaiting checks/merge). "Success" means the build work is sound — it does not assert the change reached an environment. The env transition in 3d gates on the PR actually being merged; an open PR does not advance the ticket to a
done env status.
- Blocked by jira-verify pre-flight gate —
lisa:jira-agent itself transitions the ticket to Blocked and reassigns to Reporter. This is correct and expected — let it stand. Record the outcome and move on.
- Duplicate already fixed —
lisa:jira-agent / lisa:ticket-triage returned DUPLICATE_ALREADY_FIXED with a canonical ticket reference and empirical base-branch evidence. Post the triage finding, ensure the native duplicates <canonical> link exists, transition to the terminal $DONE status with resolution Duplicate, and do not open a PR. If the canonical fix is merged but not yet on the production branch, the close comment must say the production error can recur until the canonical ticket promotes and that recurrence is tracked by the canonical ticket; do not reopen this duplicate for that recurrence.
- Blocked by ticket-triage ambiguities —
lisa:jira-agent posts findings and stops. The ticket stays in $CLAIMED. Surface to human; do not auto-transition. Record under "Errors" with reason "Triage found ambiguities — see comments on <ticket-key>".
- Errored — exception, missing config, etc. Leave the ticket in
$CLAIMED for human investigation. Record under "Errors" with the exception summary.
3c.1 Close duplicate already fixed
Run this only when the returned triage verdict is exactly DUPLICATE_ALREADY_FIXED.
- Verify the structured result includes a canonical ticket reference, the canonical PR/commit, and empirical evidence that the canonical fix is present on the base branch. If any piece is missing, treat the outcome as Held instead of closing.
- Post or preserve the triage-finding comment that explains why this ticket is a duplicate and names the canonical ticket.
- Ensure the native
duplicates <canonical> link exists through lisa:atlassian-access.
- Resolve the terminal
$DONE value exactly as in Phase 3d. For env-keyed workflows, duplicate closeout uses the production/final done status, not an intermediate On Dev/On Stg waypoint.
- Transition to
$DONE with JIRA resolution Duplicate. If acli cannot set resolution on transition, use the Atlassian REST transition-with-fields path exposed by lisa:atlassian-access, or a documented follow-up edit that sets the resolution immediately after transition. Do not report success with an empty resolution when the workflow requires one.
- Post a close comment naming the canonical ticket, PR/commit, and base-branch evidence.
If the canonical fix is merged but not yet present on the production branch, append the production-promotion caveat to the close comment: the production error can recur until the canonical ticket promotes, and recurrence is tracked by the canonical ticket rather than by reopening this duplicate.
This path is distinct from BLOCKED: ambiguity, open blockers, and duplicate-of-open findings remain held for human action and must not be auto-closed.
3d. Transition to $DONE (only after the PR is merged)
A done env status (On Dev, On Stg, or the terminal value) asserts that the code has actually reached that environment. Never set it for a PR that is merely open: auto-merge can be blocked indefinitely (a required rebase / BEHIND branch, failing checks, an unaddressed review), and the change may never land. Setting On Stg on an open PR makes a ticket claim a deploy that never happened. Transition only after confirming the PR merged.
If lisa:jira-agent returned Success:
- Confirm the PR merged. Read the live state of the ticket's PR —
gh pr view <pr> --json state,mergedAt,mergeStateStatus,url:
- Merged (
state == MERGED) → proceed to resolve and apply $DONE below. Where the env deploy is observable (a deploy workflow run / deployment status keyed to the merged-into branch via deploy.branches), confirm it did not fail before transitioning; a still-running deploy is treated like an open PR (leave in $CLAIMED for a later cycle), a failed deploy is recorded as an Error.
- Open / not yet merged → do not transition. The build is sound but the change has reached no environment yet. Record the ticket under "PR open — awaiting merge" in the summary (with the PR URL and its
mergeStateStatus), leave it in $CLAIMED, and stop. A later lisa:repair-intake cycle drives the open PR to merge — re-syncing a BEHIND branch so the already-enabled auto-merge can land, or surfacing a real blocker — and, once it is merged, applies this same env transition. Do not comment "Build complete" or file anything: the work is in-flight, not done.
- Closed without merging → record an Error (the PR was abandoned unmerged); leave the ticket in
$CLAIMED for human investigation.
- Resolve
$DONE for this ticket's PR base branch using the Workflow resolution algorithm above. If env can't be resolved and done is env-keyed, record an Error and skip this transition — never guess.
- Determine whether
$DONE is the true terminal done value per the leaf-only-lifecycle rule's Terminal native closure section:
- If
jira.workflow.done is a string, that status is terminal.
- If
jira.workflow.done is an object, only the production/final environment value is terminal (default: Done). Intermediate env statuses such as On Dev and On Stg are not terminal and must remain unresolved / open.
- If the project uses a different final environment name, resolve it from the configured deployment topology; if ambiguous, record an Error and do not finalize native resolution.
- Invoke
lisa:atlassian-access operation: transition key: <TICKET> to: "$DONE".
- If
$DONE is terminal, verify the resulting JIRA issue is natively closed/resolved: status category is Done, and resolution is set when the project's workflow requires one. If the transition screen requires an explicit resolution, use the configured default resolution if present; otherwise record an Error naming the missing workflow setup rather than silently landing in an unresolved Done-named status.
- Post a
[claude-build-intake] comment via lisa:atlassian-access operation: comment key: <TICKET> body: "Build complete. PR <URL> merged. Transitioned to $DONE." Include whether terminal native resolution was verified, already satisfied, skipped for an intermediate env, or blocked by workflow setup.
For any non-Success outcome, do NOT transition. The ticket sits in $CLAIMED (or wherever lisa:jira-agent left it for the Blocked case) — the cycle's job is done; humans take it from there.
3d.1 Roll up the parent chain (forward rollup)
Run this only after a successful $DONE transition in 3d. This is the forward arm of the leaf-only-lifecycle rule's "rollup is evaluated whenever a child transitions" requirement: a leaf reaching $DONE may complete its parent Story, which may in turn complete its Epic. Without this step a fully-built parent stays open until the recovery lisa:repair-intake cron happens to run.
- Resolve the ticket's parent using the same hierarchy
lisa:jira-read-ticket uses — the native Epic → Story → Sub-task parentage (parent field / Epic link). If the ticket has no parent, skip — nothing to roll up.
- Walk up the ancestor chain bottom-up (Sub-task → Story → Epic): for each ancestor invoke
lisa:jira-sync <ANCESTOR-KEY> --rollup. That skill derives the ancestor's status from its children per leaf-only-lifecycle, applies it via lisa:atlassian-access operation: transition only when it differs (never the build-ready status), and performs terminal native resolution (statusCategory = Done with a resolution when the workflow requires one) when the derived env is the terminal $DONE. It is idempotent and safe-defaults (suggests, does not guess) when the rolled state is ambiguous.
- Stop walking up when an ancestor has no parent, or when
--rollup reports no change. Record each rolled-up ancestor and its derived state in the summary.
This does not re-implement the state machine — it delegates to lisa:jira-sync --rollup, the single rollup implementation lisa:repair-intake also uses, so the forward and recovery paths can never drift. Children closed outside this flow are not observed here; lisa:repair-intake remains the recovery net for those.
3e. Stop
Stop immediately after the first claimed, skipped, blocked, held, or errored ticket. Later scheduler invocations process the remaining ready tickets.
Phase 4 — Summary report
## jira-build-intake summary
Query: <JQL or project key>
Cycle started: <ISO timestamp>
Cycle completed: <ISO timestamp>
Tickets processed: <n>
- $DONE (build complete, PR merged): <n>
- <ticket-key> <summary> → PR <URL>
- PR open — awaiting merge (left in $CLAIMED for repair-intake): <n>
- <ticket-key> <summary> → PR <URL> (mergeStateStatus: <state>)
- Skipped (container — leaf-only-lifecycle): <n>
- <ticket-key> <summary> — build-ready on a parent with open child work; lifecycle-repair comment posted
- Duplicate already fixed (closed as Duplicate): <n>
- <ticket-key> <summary> — duplicate of <canonical>; no PR opened
- Blocked (pre-flight verify failed): <n>
- <ticket-key> <summary> — see ticket comments
- Held (triage found ambiguities): <n>
- <ticket-key> <summary> — see ticket comments
- Errors: <n>
- <ticket-key> <summary> — <reason>
Total PRs opened: <n>
Idempotency & safety
- Leaf-only claim gate runs first: Phase 3a classifies each candidate before any claim; a container with open child work (or a childless Epic) is skipped/safe-blocked, never claimed (the
leaf-only-lifecycle rule's claim-time arm). The safe-block comment is idempotent — a re-entrant cycle does not re-post it.
- Claim-first ordering:
$CLAIMED set BEFORE lisa:jira-agent invocation — no double-pickup.
- No writes outside the lifecycle: this skill only transitions
$READY → $CLAIMED and $CLAIMED → $DONE, then verifies terminal native resolution when $DONE is the true terminal state per leaf-only-lifecycle. Every other status change is owned by lisa:jira-agent (which suggests transitions but only auto-transitions on the verify-FAIL path).
- Duplicate terminal exception:
DUPLICATE_ALREADY_FIXED is the only triage outcome that may close a claimed ticket without a PR from this cycle. It must include a canonical ticket reference and empirical base-branch evidence, and it resolves as Duplicate rather than as completed build work.
- Terminal native closure: for terminal
$DONE, the resulting JIRA issue must be in a resolved / closed state (statusCategory = Done and resolution set when required). Intermediate env statuses stay unresolved / open.
- One item per cycle: per-ticket exceptions are caught and recorded, then the cycle exits. The scheduler owns retrying or moving on to the next ready item.
- Single cycle per query: do not run two
lisa:jira-build-intake cycles concurrently against overlapping queries — concurrent claims could race. The scheduling layer (when added) is responsible for serialization.
- Never invent a transition: if
$CLAIMED or $DONE aren't valid transitions in the project's workflow, stop and report rather than guessing alternative names.
Configuration
Reads atlassian.cloudId, jira.project, and jira.workflow.{ready,claimed,done} from .lisa.config.json (with .lisa.config.local.json overriding per key). The project key is also accepted as $ARGUMENTS for ad-hoc invocations.
Status role names default to:
ready → "Ready"
claimed → "In Progress"
done → env-keyed map { "dev": "On Dev", "staging": "On Stg", "production": "Done" }
If a project uses different names (e.g. Open instead of TODO, In Development instead of In Progress, Code Review for terminal), override the relevant key in .lisa.config.json jira.workflow.*. The setup skills (/lisa:setup:jira) handle this interactively.
Per-invocation overrides via $ARGUMENTS (e.g. claim_status="In Development") are accepted as a secondary escape hatch but .lisa.config.json is the canonical source.
If a ready-equivalent status does not exist in the JIRA project's workflow, this skill cannot run. The remediation is to add it to the project workflow scheme — JIRA admin task, not something this skill can do.
| Field / variable | Default | Purpose |
|---|
.lisa.config.json jira.project | (from $ARGUMENTS) | Project key for the default JQL |
.lisa.config.json atlassian.cloudId | — | Atlassian Cloud site UUID (required) |
.lisa.config.json jira.workflow.ready | Ready | The status that signals "human says this is buildable" |
.lisa.config.json jira.workflow.claimed | In Progress | The intermediate status the agent sets on pickup |
.lisa.config.json jira.workflow.done | env-keyed map (dev/staging/production) or string | The status set after a successful build; env-aware |
.lisa.config.json deploy.branches | — | Reverse-lookup map for env inference from PR base branch |
Rules
- Claim leaves only. Per the
leaf-only-lifecycle rule, never claim a container — a ticket with open child work, or a childless Epic — even if it carries the build-ready status. Skip or safe-block it (Phase 3a); never silently implement a container.
- Never transition a ticket the cycle didn't claim. The
$CLAIMED transition is the signature of cycle ownership.
- Never bypass
lisa:jira-agent to do build work directly. lisa:jira-agent owns the per-ticket lifecycle (read, verify, triage, route, sync, evidence). This skill is the dispatcher, not the builder.
- Never auto-transition past
$DONE. Downstream statuses are owned by QA / product / a future verification-intake skill — not this one.
- Never resolve / close a JIRA ticket at intermediate env statuses (
On Dev, On Stg, or configured equivalents). Native resolution is terminal-only.
- If the ticket has no Validation Journey or no sign-in credentials in its description,
lisa:jira-agent's pre-flight verify will catch it and transition to Blocked — don't try to fix the ticket from here. Pre-flight gating is lisa:jira-agent's job; running build work on a thin ticket produces broken work.
- On any unexpected response from
lisa:jira-agent (status it doesn't claim, missing PR URL on success, etc.), record as Error and surface — never assume.
- Never pick an arbitrary env for
$DONE resolution. If done is a map and env is ambiguous, fail loudly.