{
"meta": {
"agent": "planner",
"task_id": "556",
"title": "BJ-16: E2E mock server — Atlassian REST APIs",
"created_at": "2026-04-23T17:13:31Z"
},
"inputs": [
{
"name": "issue_556",
"type": "link",
"ref": "https://github.com/AgentSDE/agent-core/issues/556",
"notes": "BJ-16 spec and acceptance criteria"
},
{
"name": "bj8_issue",
"type": "link",
"ref": "https://github.com/AgentSDE/agent-core/issues/548",
"notes": "BitbucketService surface this mock must cover"
},
{
"name": "bj9_issue",
"type": "link",
"ref": "https://github.com/AgentSDE/agent-core/issues/549",
"notes": "JiraService surface this mock must cover"
},
{
"name": "target_repo",
"type": "context",
"ref": "AgentSDE/agent-core-e2e @ rc/atlassian-integration",
"notes": "Mock lives in e2e repo, not agent-core"
},
{
"name": "e2e_agents_md",
"type": "file",
"ref": "/home/agent/repos/agent-core-e2e/AGENTS.md",
"notes": "Tiered jest config pattern, tier config registration rule"
}
],
"outputs": [
{
"name": "plan",
"type": "spec",
"format": "md",
"content": "plan.md"
}
],
"files": [
{
"path": "test/mocks/atlassian-mock-server.ts",
"action": "create",
"reason": "Embedded HTTP mock for Bitbucket + Jira + OAuth stubs with request recording"
},
{
"path": "test/mocks/global-setup.ts",
"action": "create",
"reason": "Jest globalSetup — boot mock singleton, set BITBUCKET_*/JIRA_* env vars"
},
{
"path": "test/mocks/global-teardown.ts",
"action": "create",
"reason": "Jest globalTeardown — stop singleton"
},
{
"path": "test/mocks/atlassian-mock-server.spec.ts",
"action": "create",
"reason": "Unit tests for mock class"
},
{
"path": "jest.e2e.config.js",
"action": "modify",
"reason": "Wire globalSetup/globalTeardown"
},
{
"path": "package.json",
"action": "inspect",
"reason": "Confirm no new deps needed"
}
],
"steps": [
{
"id": "S1",
"summary": "Implement AtlassianMockServer class with start/stop/url/resetRequests/getRequests and a routed dispatcher using Node http",
"acceptance": [
"start() binds port 0 and returns a URL",
"stop() closes the server cleanly",
"Each request is recorded with method, path, query, headers, body",
"resetRequests() clears the in-memory log",
"Unknown routes return 404 with a 'unmocked route' marker and log the request"
],
"depends_on": []
},
{
"id": "S2",
"summary": "Add OAuth stub handlers at /site/oauth2/access_token and /oauth/token returning a canned bearer token",
"acceptance": [
"POST /site/oauth2/access_token returns 200 with {access_token, token_type, expires_in, refresh_token}",
"POST /oauth/token returns the same canned shape",
"Responses do not expire within a test run"
],
"depends_on": [
"S1"
]
},
{
"id": "S3",
"summary": "Add Bitbucket /2.0/* handlers covering the BJ-8 happy-path surface with minimal canned bodies",
"acceptance": [
"Create/list/merge/close PR, updatePRBranch, postComment, editComment, label add/remove routes return 200 canned JSON",
"File get/put, branch create/delete/default-sha, commit-status, review-status routes return 200 canned JSON",
"Response shapes match Bitbucket Cloud v2 envelope conventions",
"Requests are recorded via the S1 recorder"
],
"depends_on": [
"S1"
]
},
{
"id": "S4",
"summary": "Add Jira /ex/jira/{cloudId}/* handlers covering the BJ-9 happy-path surface with minimal canned bodies",
"acceptance": [
"getIssue, comment post/edit, transitions list + POST, labels, assignee, priority, issueLink, JQL search all return 200 canned JSON",
"Response shapes match Jira Cloud REST v3 conventions",
"Requests are recorded via the S1 recorder"
],
"depends_on": [
"S1"
]
},
{
"id": "S5",
"summary": "Add global-setup.ts and global-teardown.ts and wire them into jest.e2e.config.js",
"acceptance": [
"globalSetup boots a singleton mock and stores it on globalThis",
"BITBUCKET_BASE_URL, JIRA_BASE_URL, BITBUCKET_OAUTH_URL, ATLASSIAN_OAUTH_URL env vars are set to the mock URL",
"globalTeardown stops the mock without leaking handles",
"jest.e2e.config.js references both files"
],
"depends_on": [
"S1",
"S2",
"S3",
"S4"
]
},
{
"id": "S6",
"summary": "Add atlassian-mock-server.spec.ts covering lifecycle, route responses, OAuth stub, unmocked 404, and request introspection",
"acceptance": [
"Spec passes under npm run test",
"Covers start/stop, at least one Bitbucket and one Jira route, OAuth stub, 404 path, resetRequests(), getRequests() shape"
],
"depends_on": [
"S1",
"S2",
"S3",
"S4"
]
}
],
"risks": [
{
"risk": "Mock response shapes drift from real Atlassian APIs",
"mitigation": "Derive shapes from BJ-8/BJ-9 service method signatures; inline-comment speculative fields with the Atlassian doc reference"
},
{
"risk": "Jest globalSetup shares one server across workers",
"mitigation": "Rely on resetRequests() per test for isolation; port 0 avoids collisions with non-Jest processes"
},
{
"risk": "Env var overrides may leak into unrelated tests",
"mitigation": "Only set in globalSetup; restore/unset in globalTeardown"
}
],
"assumptions": [
"Target branch in agent-core-e2e is rc/atlassian-integration (stated in issue)",
"No new npm dependency is required — Node built-in http suffices",
"BITBUCKET_*/JIRA_* env var names are not yet defined in this repo; this task introduces them",
"Confluence and other Atlassian products are out of scope for this wave"
],
"open_questions": [
"Should tier-specific jest configs (tier1/2/2d) also wire globalSetup, or only jest.e2e.config.js? Plan assumes only jest.e2e.config.js for now."
]
}