{
"meta": {
"agent": "planner",
"task_id": "549",
"title": "BJ-9: JiraService (issue-oriented surface)",
"created_at": "2026-04-23T17:12:46Z"
},
"inputs": [
{
"name": "issue-549",
"type": "link",
"ref": "AgentSDE/agent-core#549",
"notes": "BJ-9 issue body"
},
{
"name": "epic-539",
"type": "link",
"ref": "AgentSDE/agent-core#539",
"notes": "Atlassian integration epic (Wave 2)"
},
{
"name": "deps-bj3-4-5",
"type": "link",
"ref": "#543,#544,#545",
"notes": "Provide Atlassian PlatformAuthProvider"
},
{
"name": "AGENTS.md",
"type": "file",
"ref": "AGENTS.md",
"notes": "Wave-dependency guidance: stub missing upstream modules"
},
{
"name": "GitHubService",
"type": "file",
"ref": "src/github/github.service.ts",
"notes": "Reference shape for request helper + 429 retry"
}
],
"outputs": [
{
"name": "plan.md",
"type": "spec",
"format": "md",
"content": "See plan/plan.md"
}
],
"files": [
{
"path": "src/jira/jira.service.ts",
"action": "create",
"reason": "Implement 11-method issue-oriented Jira API service"
},
{
"path": "src/jira/jira.module.ts",
"action": "create",
"reason": "Register JIRA_SERVICE factory provider"
},
{
"path": "src/jira/index.ts",
"action": "create",
"reason": "Barrel export"
},
{
"path": "src/jira/jira.service.spec.ts",
"action": "create",
"reason": "Unit tests for all methods + 429/401 paths"
},
{
"path": "src/config/config.schema.ts",
"action": "modify",
"reason": "Add required JIRA_CLOUD_ID"
},
{
"path": "src/app.module.ts",
"action": "modify",
"reason": "Import JiraModule"
},
{
"path": ".env.example",
"action": "modify",
"reason": "Document JIRA_CLOUD_ID"
},
{
"path": "CLAUDE.md",
"action": "modify",
"reason": "List jira module + env var"
}
],
"steps": [
{
"id": "S1",
"summary": "Implement JiraService with 11 methods, 429 retry, 401 refresh",
"acceptance": [
"All 11 methods implemented with correct REST v3 endpoints",
"Private request() attaches Bearer token from PlatformAuthProvider.getToken()",
"429 response triggers one retry honoring Retry-After header",
"401 response triggers one token refresh + retry; propagates if still 401",
"Constructor throws configuration error when JIRA_CLOUD_ID is unset",
"No `any` types; passes strict lint"
],
"depends_on": []
},
{
"id": "S2",
"summary": "Wire JiraModule (factory for JIRA_SERVICE), register JIRA_CLOUD_ID in config schema, add JiraModule to AppModule",
"acceptance": [
"JiraModule provides JIRA_SERVICE via useFactory + inject",
"JiraModule exports JIRA_SERVICE and JiraService",
"config.schema.ts adds JIRA_CLOUD_ID as required string",
"AppModule imports JiraModule",
"Barrel src/jira/index.ts exports JiraService, JiraModule, JIRA_SERVICE",
"npm run build succeeds"
],
"depends_on": [
"S1"
]
},
{
"id": "S3",
"summary": "Unit tests covering all methods, 429 retry, 401 refresh, config error, empty-result paths",
"acceptance": [
"Test per method asserts URL, method, body shape",
"429 test asserts Retry-After honored and retry succeeds",
"401 test asserts getToken called twice and retry succeeds",
"Missing JIRA_CLOUD_ID test asserts startup-time throw",
"getTransitions empty response returns []",
"searchJql zero-result response returns []",
"npm run test passes"
],
"depends_on": [
"S1"
]
},
{
"id": "S4",
"summary": "Document JIRA_CLOUD_ID in .env.example and CLAUDE.md (env table + Key modules list)",
"acceptance": [
".env.example contains JIRA_CLOUD_ID entry",
"CLAUDE.md env-var table includes JIRA_CLOUD_ID row",
"CLAUDE.md Key modules list includes `jira`"
],
"depends_on": [
"S2"
]
}
],
"risks": [
{
"risk": "BJ-3/4/5 not yet merged on rc/atlassian-integration — no Atlassian-backed PlatformAuthProvider available",
"mitigation": "Provide minimal inline stub provider inside JiraModule per AGENTS.md Wave-dependency pattern; remove once BJ-3/4/5 land"
},
{
"risk": "Jira REST v3 shape variations (labels/priority live under `fields` with update semantics) lead to incorrect PUT payloads",
"mitigation": "Use `update.labels[{add}|{remove}]` and `fields.assignee`/`fields.priority` per official v3 docs; cover each shape with a spec"
}
],
"assumptions": [
"BJ-3/4/5 expose an injection token whose provider implements the existing PlatformAuthProvider interface",
"Jira REST API v3 is the intended version (not v2)",
"`setAssignee` accepts an accountId string; `setPriority` accepts a priority name or id string",
"One retry (not exponential backoff) is sufficient for 429/401 — matches existing GitHubService behavior"
],
"open_questions": [
"Is the Atlassian auth provider registered under PLATFORM_AUTH_PROVIDER or a new ATLASSIAN_AUTH_PROVIDER token?"
]
}