Skip to content

Jira poll adapter (NormalizedEvent extension)

Poll input driver mapping for Jira work items, defined in ADR 0063. This document extends NormalizedEvent v1 for jira-poll input drivers until the changes are merged into normalized-event.schema.json.

Scope

  • In scope: Jira issues polled by fullsend poll --input-driver jira-poll. Events use entity.kind: work_item only.
  • Out of scope: Jira webhooks, Service Desk, sprint/board events, and forge change-proposal routing (e.g. /fs-fix) — those stages require a change_proposal entity and are triggered from forge webhooks or poll drivers on the code repo, not from Jira issue comments alone.

Schema extensions

The following fields are defined in normalized-event.schema.json:

FieldDefinition
source.systemEnum includes jira
entity.keyOptional for GitHub; required when source.system is jira

When source.system is jira, entity.key MUST be present (e.g. PROJ-123).

Top-level fields

FieldJira poll value
repoTarget repo slug from poll context (GITHUB_REPOSITORY or config).
source.systemjira
source.raw_typeNative Jira object: issue, comment, changelog
source.raw_actionNative action when applicable: created, updated, deleted
entity.kindwork_item
entity.idJira numeric issue id (fields or search result id)
entity.keyIssue key (PROJ-123)
entity.urlBrowse URL ({base}/browse/{key})
entity.linked_change_proposalOmitted — Jira poll emits work-item events only
actorComment/changelog author (see below)
transitionMapped semantic transition (see below)
state.labelsCurrent Jira label names at event time

Transition mapping

Jira signaltransition.kindSub-fields
Issue createdopened
Issue reopenedreopened
Summary/description/fields updatededited
Label addedlabel_changedlabel.name, label.action: added
Label removedlabel_changedlabel.name, label.action: removed
Comment addedcomment_addedcomment.body, optional command / instruction
Issue closedclosed

Comment parsing matches the gha-event adapter: command is the first whitespace-delimited token of the first line; instruction is the remainder of the first line after the command (same rules as README — execution ref projection).

Actor mapping

FieldSource
actor.idJira accountId (preferred) or name when accountId unavailable
actor.kindbot when Jira account type is app or display name matches automation pattern; else human
actor.roleEffective permission on the target repo when the actor maps to a forge user with repo access; otherwise map Jira project role to closest ADR 0054 role (write for Developers, read for Reporter, admin for Administrators). When membership cannot be resolved, use external.
actor.is_entity_authortrue when actor is the issue reporter

Authorization is enforced by fullsend dispatch per ADR 0054after normalization. The poll loop does not bypass the gate.

State

  • state.labels — label names from fields.labels at event time.
  • state.change_proposal — omitted. Change-proposal stages (fix, PR-linked review, merge retro) are forge-scoped; harness CEL triggers for those stages MUST require entity.kind == 'change_proposal' or equivalent guards.

Execution ref projection

When source.system is jira, projection supplements the GitHub-shaped event_payload fields:

Execution ref / envSource
FULLSEND_WORK_ITEM_URLentity.url
FULLSEND_WORK_ITEM_SOURCEjira
FULLSEND_WORK_ITEM_KEYentity.key
event_payload.commenttransition.comment when present
GITHUB_ISSUE_URLOmit or empty — not a GitHub issue
status-numberentity.id (numeric Jira id)

Harnesses and pre-scripts that require forge URLs MUST use FULLSEND_WORK_ITEM_* for Jira-sourced runs.

Example

Issue comment with slash command:

json
{
  "repo": "acme/platform",
  "source": {
    "system": "jira",
    "raw_type": "comment",
    "raw_action": "created"
  },
  "entity": {
    "kind": "work_item",
    "id": 10042,
    "key": "PROJ-123",
    "url": "https://acme.atlassian.net/browse/PROJ-123"
  },
  "actor": {
    "id": "557058:abc123def456",
    "kind": "human",
    "role": "write",
    "is_entity_author": false
  },
  "transition": {
    "kind": "comment_added",
    "comment": {
      "command": "/fs-triage",
      "body": "/fs-triage check acceptance criteria",
      "instruction": "check acceptance criteria"
    }
  },
  "state": {
    "labels": ["needs-info", "bug"]
  }
}

CEL triggers

Harness trigger expressions use the same event root variable as GitHub events. Example:

yaml
trigger: event.source.system == 'jira' && event.transition.kind == 'comment_added' && event.transition.comment.command == '/fs-triage'

Routing logic lives on harness files per ADR 0061, not in poll config.