# ISS-0021: Jira search-issues API returns HTTP 410 (v2 deprecated)

## Background

Discovered in workspace `ws-1776139348995-a7101b3a3` (O11Y-2392287) on dev environment.

The agent needed to search for other O11Y alerts on the same cluster during the incident time window. Instead of using the `jira_api.py search-by-cluster` subcommand (which already uses v3), the agent constructed a **raw curl call** to `/rest/api/2/search` — which Atlassian has deprecated and returns HTTP 410.

## What happened

1. User asked: "这个集群在这个时间点还有什么别的告警么？"
2. Agent built a raw curl call using `/rest/api/2/search` endpoint
3. Got HTTP 410 (Gone) — Atlassian fully deprecated this endpoint
4. Agent retried with `/rest/api/3/search/jql` (correct endpoint) but **did not pass `fields` in POST body**
5. Response returned only `{"id": "7396931"}` per issue — no key, summary, or dates
6. Agent parsed the empty fields as `? | ? | ?` (19 rows of question marks)
7. Agent debugged the response structure, discovered only `id` was present
8. Finally added `fields` to POST body and got correct results on 4th attempt

## Observed errors

**Tool call 0** (failed):
```
KeyError: 'key'
```
Agent expected `issue["key"]` in the response but v3 without explicit fields returns only `id`.

**Tool call 1** (wrong output):
```
? | ? | ?
? | ? | ?
... (19 rows)
```
Agent got 19 results but all fields were empty/missing.

**Tool call 2** (debug):
```
total: 19
first issue keys: ['id']
first issue: {"id": "7396931"}
```
Confirmed: v3 response only has `id` unless fields are requested.

**Tool call 3** (success):
```
total: 19
7396931 | [PROD]TiFlashPerformanceJitterRiskForWetech | 2026-04-13T02:05:11
...
```
With explicit `fields` in POST body, correct data returned.

## Root cause analysis

Two separate issues:

1. **The agent bypassed `jira_api.py`** and constructed raw curl calls. The script's `search-by-cluster` and `search-by-alert-name` subcommands already use v3 correctly. But the agent didn't know it could search by free-text JQL via the script — there's no generic `search-issues --jql "..."` subcommand.

2. **`get_issue` and `get_comments` still use v2** (`/rest/api/2/issue/{key}` and `/rest/api/2/issue/{key}/comment`). These haven't broken yet but will when Atlassian deprecates v2 for these endpoints too.

## Current code state

File: `agentkit/skills/builtin/jira/scripts/jira_api.py`

- `_search_jql()` (line ~118): Already uses `POST /rest/api/3/search/jql` with cursor pagination. **This is correct.**
- `get_issue()` (line ~107): Uses `GET /rest/api/2/issue/{key}`. **Needs migration.**
- `get_comments()` (line ~115): Uses `GET /rest/api/2/issue/{key}/comment`. **Needs migration.**
- `add_comment()` (line ~181): Uses `POST /rest/api/2/issue/{key}/comment`. **Needs migration.**
- No `search-issues --jql` generic subcommand exists — agent has to use `search-by-cluster`, `search-by-tenant`, or `search-by-alert-name`.

## Fix plan

### Step 1: Migrate remaining v2 endpoints to v3

In `jira_api.py`:

```python
# get_issue: /rest/api/2/issue/{key} -> /rest/api/3/issue/{key}
def get_issue(args):
    return jira_request("GET", f"/rest/api/3/issue/{args.issue_key}")

# get_comments: /rest/api/2/issue/{key}/comment -> /rest/api/3/issue/{key}/comment
def get_comments(args):
    return jira_request("GET", f"/rest/api/3/issue/{args.issue_key}/comment")

# add_comment: /rest/api/2/issue/{key}/comment -> /rest/api/3/issue/{key}/comment
# Note: v3 comment body uses ADF (Atlassian Document Format), not plain text
def add_comment(args):
    return jira_request(
        "POST",
        f"/rest/api/3/issue/{args.issue_key}/comment",
        payload={
            "body": {
                "type": "doc",
                "version": 1,
                "content": [{"type": "paragraph", "content": [{"type": "text", "text": args.body}]}]
            }
        },
    )
```

### Step 2: Add generic `search-issues` subcommand

Add a `search-issues --jql "..." --fields key,summary,...` subcommand so the agent doesn't have to construct raw curl for custom JQL queries:

```python
def search_issues(args):
    fields = [f.strip() for f in args.fields.split(",")]
    return _search_jql(args.jql, fields, args.max_results, args.next_page_token)
```

### Step 3: Update Jira SKILL.md

Document the new `search-issues` subcommand so the agent knows to use it instead of raw curl.

## Verification

After fixing, run:
```bash
python jira_api.py search-issues --jql "project = O11Y AND text ~ 'cluster_id_here'" --fields key,summary,created
python jira_api.py get-issue --issue-key O11Y-2392287
python jira_api.py get-comments --issue-key O11Y-2392287
```

All should return valid data without 410 errors.
