diff --git a/skills/triage/SKILL.md b/skills/triage/SKILL.md index b370f5e..55fafa9 100644 --- a/skills/triage/SKILL.md +++ b/skills/triage/SKILL.md @@ -1,6 +1,6 @@ --- name: triage -description: Use when converting a bug report or feature request — a screenshot and/or a short message, typically forwarded from the company Telegram chat — into a Jira issue routed to the right developer. Triggers on /gw-triage:triage, "crea una issue da questo", "segnala questo bug", or a pasted/dropped Telegram report with intent to track it. +description: Use when converting a bug report or feature request — a screenshot and/or a short message, typically forwarded from the company Telegram chat — into a Jira issue routed to the right developer. Triggers on /gw-triage:triage, $triage, "crea una issue da questo", "segnala questo bug", or a pasted/dropped Telegram report with intent to track it. --- # Triage — da segnalazione a issue Jira @@ -11,26 +11,63 @@ well-formed Jira issue assigned to the right developer. **All interaction with the user happens in Italian.** This file is English for precision; never quote it to the user. -The Atlassian MCP tools referenced below live under the -`mcp__plugin_atlassian_atlassian__` prefix. If they are deferred, load -them in ONE ToolSearch call before Step 0: -`select:mcp__plugin_atlassian_atlassian__getAccessibleAtlassianResources,mcp__plugin_atlassian_atlassian__searchJiraIssuesUsingJql,mcp__plugin_atlassian_atlassian__createJiraIssue,mcp__plugin_atlassian_atlassian__addCommentToJiraIssue` +## Environment + +- **Root**: `${CLAUDE_PLUGIN_ROOT}` if that variable is set; otherwise + the real path of this skill's own directory (resolve symlinks, e.g. + with `realpath`), two levels up. `config/` and `knowledge/` below + are relative to this root. +- **Netrc**: `~/.config/gw-triage/netrc` — Jira credentials, written + by the `setup` skill. +- **Mode** — how Jira is reached: + - **MCP mode** (Claude Code): the Atlassian MCP tools (prefix + `mcp__plugin_atlassian_atlassian__`) are available. If they are + deferred, load them in ONE ToolSearch call before Step 0: + `select:mcp__plugin_atlassian_atlassian__getAccessibleAtlassianResources,mcp__plugin_atlassian_atlassian__searchJiraIssuesUsingJql,mcp__plugin_atlassian_atlassian__createJiraIssue,mcp__plugin_atlassian_atlassian__addCommentToJiraIssue` + - **REST mode** (Codex, or any platform without those tools): curl + against the Jira Cloud REST API v2, authenticated with + `--netrc-file ~/.config/gw-triage/netrc`. `` in the URLs + below is the `site` value from routing.json; `cloudId` is not + used in REST mode. + + Exception: on Claude Code (recognizable by `CLAUDE_PLUGIN_ROOT` + being set), MCP is the intended path — if the tools are missing, do + NOT fall back to REST; stop with the install guide in Step 0. + +For REST calls that send a JSON body, write the body to a temp file +first (`mktemp`) and pass it with `-d @` — never inline JSON +with user text on the command line. ## Step 0 — Preflight +**MCP mode** + 1. Call `getAccessibleAtlassianResources`. If the tool is missing or returns an authentication error, STOP and print this guide in Italian, then end the turn: - installa il plugin Atlassian: `/plugin install atlassian@claude-plugins-official` - esegui `/mcp`, seleziona `atlassian` e completa il login nel browser con l'account aziendale - poi rilancia `/gw-triage:triage` -2. Run `test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo ok || echo missing`. - If `missing`: check whether `~/.claude/settings.json` has - `env.JIRA_EMAIL`/`env.JIRA_API_TOKEN`. If yes, the session predates - the config: tell the user (Italian) to restart Claude Code to enable - automatic attachments. If no, tell them the screenshot cannot be - attached automatically and that `/gw-triage:setup` configures it in - a couple of minutes. Either way, say it once and proceed. +2. Attachment credentials: + `test -r ~/.config/gw-triage/netrc && echo netrc || (test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo env || echo missing)`. + Remember the answer for Step 7. If `missing`, tell the user + (Italian) the screenshot cannot be attached automatically and that + `/gw-triage:setup` configures it in a couple of minutes. Say it + once and proceed. + +**REST mode** — the netrc is required; it is the only transport. + +1. `test -r ~/.config/gw-triage/netrc && echo ok || echo missing` — + if `missing`, STOP and print in Italian: serve il token API Jira; + esegui `$setup` e poi rilancia `$triage`. +2. Verify: + + curl -s -o /dev/null -w "%{http_code}" \ + --netrc-file ~/.config/gw-triage/netrc \ + /rest/api/2/myself + + Anything but `200` → STOP (Italian): token scaduto o revocato, + rilancia `$setup`. ## Step 1 — Input @@ -44,8 +81,8 @@ Expect a short message (usually Italian) and optionally a screenshot. ## Step 2 — Load routing and knowledge -Read `${CLAUDE_PLUGIN_ROOT}/config/routing.json` and every `.md` file -in `${CLAUDE_PLUGIN_ROOT}/knowledge/` except `README.md`. +Read `/config/routing.json` and every `.md` file in +`/knowledge/` except `README.md`. ## Step 3 — Classify @@ -64,20 +101,46 @@ question in Italian (e.g. "Succede solo su iOS o anche su Android?"). Never more than one question; otherwise decide and state the assumption in the draft. -If no knowledge profile covers the symptoms, classify using the routing.json area list alone and state the lower confidence explicitly in the draft. +If no knowledge profile covers the symptoms, classify using the +routing.json area list alone and state the lower confidence explicitly +in the draft. ## Step 4 — Duplicate check Extract 2–4 distinctive keywords (include Italian and English variants -of domain terms). Call `searchJiraIssuesUsingJql` with: +of domain terms). Search with JQL `project = AND text ~ "" AND statusCategory != Done ORDER BY created DESC` -(maxResults 10). Judge similarity by symptom, not wording. +(maxResults 10): + +- MCP mode: `searchJiraIssuesUsingJql`. +- REST mode (note: search is the one call NOT on v2 — Atlassian + removed `/rest/api/2/search` in 2025; `/rest/api/3/search/jql` is + its replacement): + + curl -s --netrc-file ~/.config/gw-triage/netrc -G \ + --data-urlencode 'jql=' \ + --data-urlencode 'maxResults=10' \ + --data-urlencode 'fields=summary,status,issuetype' \ + "/rest/api/3/search/jql" + +Judge similarity by symptom, not wording. If a likely duplicate exists: show it (key, title, status) and ask (Italian) whether to comment on it instead of creating a new issue. -If yes → `addCommentToJiraIssue` with the new report's details (and -note the screenshot can't be attached to a comment automatically), -report the link, stop. +If yes, add a comment with the new report's details (and note the +screenshot can't be attached to a comment automatically), report the +link, stop: + +- MCP mode: `addCommentToJiraIssue`. +- REST mode — write `{"body": ""}` to a temp file, then: + + curl -s -o /tmp/gw-triage-comment.json -w "%{http_code}" \ + --netrc-file ~/.config/gw-triage/netrc \ + -H "Content-Type: application/json" \ + -X POST -d @ \ + "/rest/api/2/issue//comment" + + Success = HTTP 201. ## Step 5 — Draft (Italian) @@ -100,9 +163,33 @@ epic and assignee). ## Step 6 — Create -Call `createJiraIssue` with: `cloudId`, `projectKey`, `issueTypeName` -(`Bug` or `Task`), `summary`, `description`, the area's -`assignee.accountId`, and `additional_fields: {"parent": {"key": ""}}`. +- MCP mode: call `createJiraIssue` with `cloudId`, `projectKey`, + `issueTypeName` (`Bug` or `Task`), `summary`, `description`, the + area's `assignee.accountId`, and + `additional_fields: {"parent": {"key": ""}}`. +- REST mode — write this JSON to a temp file (description as plain + text; Jira wiki markup like `h3.` headings and `*bold*` is allowed): + + { + "fields": { + "project": {"key": ""}, + "issuetype": {"name": ""}, + "summary": "", + "description": "", + "assignee": {"accountId": ""}, + "parent": {"key": ""} + } + } + + Then: + + curl -s -o /tmp/gw-triage-create.json -w "%{http_code}" \ + --netrc-file ~/.config/gw-triage/netrc \ + -H "Content-Type: application/json" \ + -X POST -d @ \ + "/rest/api/2/issue" + + Success = HTTP 201; the issue key is in the response file. If the call fails, report the raw error with a one-line Italian summary and stop — nothing partial to clean up (the attachment step @@ -110,17 +197,22 @@ only runs after successful creation). ## Step 7 — Attach screenshot -Only if Step 0 found the env vars AND the screenshot is a file path: +Only if Step 0 found credentials (netrc or legacy env) AND the +screenshot is a file path: curl -s -o /tmp/gw-triage-attach.json -w "%{http_code}" -X POST \ -H "X-Atlassian-Token: no-check" \ - -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \ + --netrc-file ~/.config/gw-triage/netrc \ -F "file=@" \ "/rest/api/3/issue//attachments" -`` comes from routing.json. Success = HTTP 200. Any failure is -non-fatal: tell the user (Italian) to drag the image into the Jira -issue manually. +If Step 0 answered `env` (legacy install, no netrc), replace the +`--netrc-file` line with `-u "$JIRA_EMAIL:$JIRA_API_TOKEN"`, leaving +the `$` references unexpanded for the shell — never substitute the +values yourself. + +Success = HTTP 200. Any failure is non-fatal: tell the user (Italian) +to drag the image into the Jira issue manually. ## Step 8 — Report