feat(triage): dual MCP/REST mode with shared netrc credentials

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Murphy Freelance
2026-07-10 19:31:32 +02:00
parent 6525f60f86
commit 79834fee3f

View File

@@ -1,6 +1,6 @@
--- ---
name: triage 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 # 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 **All interaction with the user happens in Italian.** This file is
English for precision; never quote it to the user. English for precision; never quote it to the user.
The Atlassian MCP tools referenced below live under the ## Environment
`mcp__plugin_atlassian_atlassian__` prefix. If they are deferred, load
them in ONE ToolSearch call before Step 0: - **Root**: `${CLAUDE_PLUGIN_ROOT}` if that variable is set; otherwise
`select:mcp__plugin_atlassian_atlassian__getAccessibleAtlassianResources,mcp__plugin_atlassian_atlassian__searchJiraIssuesUsingJql,mcp__plugin_atlassian_atlassian__createJiraIssue,mcp__plugin_atlassian_atlassian__addCommentToJiraIssue` 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`. `<site>` 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 @<file>` — never inline JSON
with user text on the command line.
## Step 0 — Preflight ## Step 0 — Preflight
**MCP mode**
1. Call `getAccessibleAtlassianResources`. If the tool is missing or 1. Call `getAccessibleAtlassianResources`. If the tool is missing or
returns an authentication error, STOP and print this guide in returns an authentication error, STOP and print this guide in
Italian, then end the turn: Italian, then end the turn:
- installa il plugin Atlassian: `/plugin install atlassian@claude-plugins-official` - installa il plugin Atlassian: `/plugin install atlassian@claude-plugins-official`
- esegui `/mcp`, seleziona `atlassian` e completa il login nel browser con l'account aziendale - esegui `/mcp`, seleziona `atlassian` e completa il login nel browser con l'account aziendale
- poi rilancia `/gw-triage:triage` - poi rilancia `/gw-triage:triage`
2. Run `test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo ok || echo missing`. 2. Attachment credentials:
If `missing`: check whether `~/.claude/settings.json` has `test -r ~/.config/gw-triage/netrc && echo netrc || (test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo env || echo missing)`.
`env.JIRA_EMAIL`/`env.JIRA_API_TOKEN`. If yes, the session predates Remember the answer for Step 7. If `missing`, tell the user
the config: tell the user (Italian) to restart Claude Code to enable (Italian) the screenshot cannot be attached automatically and that
automatic attachments. If no, tell them the screenshot cannot be `/gw-triage:setup` configures it in a couple of minutes. Say it
attached automatically and that `/gw-triage:setup` configures it in once and proceed.
a couple of minutes. Either way, 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 \
<site>/rest/api/2/myself
Anything but `200` → STOP (Italian): token scaduto o revocato,
rilancia `$setup`.
## Step 1 — Input ## Step 1 — Input
@@ -44,8 +81,8 @@ Expect a short message (usually Italian) and optionally a screenshot.
## Step 2 — Load routing and knowledge ## Step 2 — Load routing and knowledge
Read `${CLAUDE_PLUGIN_ROOT}/config/routing.json` and every `.md` file Read `<root>/config/routing.json` and every `.md` file in
in `${CLAUDE_PLUGIN_ROOT}/knowledge/` except `README.md`. `<root>/knowledge/` except `README.md`.
## Step 3 — Classify ## 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 Never more than one question; otherwise decide and state the assumption
in the draft. 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 ## Step 4 — Duplicate check
Extract 24 distinctive keywords (include Italian and English variants Extract 24 distinctive keywords (include Italian and English variants
of domain terms). Call `searchJiraIssuesUsingJql` with: of domain terms). Search with JQL
`project = <projectKey> AND text ~ "<keywords>" AND statusCategory != Done ORDER BY created DESC` `project = <projectKey> AND text ~ "<keywords>" 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=<the JQL above>' \
--data-urlencode 'maxResults=10' \
--data-urlencode 'fields=summary,status,issuetype' \
"<site>/rest/api/3/search/jql"
Judge similarity by symptom, not wording.
If a likely duplicate exists: show it (key, title, status) and ask If a likely duplicate exists: show it (key, title, status) and ask
(Italian) whether to comment on it instead of creating a new issue. (Italian) whether to comment on it instead of creating a new issue.
If yes`addCommentToJiraIssue` with the new report's details (and If yes, add a comment with the new report's details (and note the
note the screenshot can't be attached to a comment automatically), screenshot can't be attached to a comment automatically), report the
report the link, stop. link, stop:
- MCP mode: `addCommentToJiraIssue`.
- REST mode — write `{"body": "<comment text>"}` 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 @<temp-file> \
"<site>/rest/api/2/issue/<KEY>/comment"
Success = HTTP 201.
## Step 5 — Draft (Italian) ## Step 5 — Draft (Italian)
@@ -100,9 +163,33 @@ epic and assignee).
## Step 6 — Create ## Step 6 — Create
Call `createJiraIssue` with: `cloudId`, `projectKey`, `issueTypeName` - MCP mode: call `createJiraIssue` with `cloudId`, `projectKey`,
(`Bug` or `Task`), `summary`, `description`, the area's `issueTypeName` (`Bug` or `Task`), `summary`, `description`, the
`assignee.accountId`, and `additional_fields: {"parent": {"key": "<area epic>"}}`. area's `assignee.accountId`, and
`additional_fields: {"parent": {"key": "<area epic>"}}`.
- 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": "<projectKey>"},
"issuetype": {"name": "<Bug|Task>"},
"summary": "<titolo>",
"description": "<descrizione>",
"assignee": {"accountId": "<area accountId>"},
"parent": {"key": "<area epic>"}
}
}
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 @<temp-file> \
"<site>/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 If the call fails, report the raw error with a one-line Italian
summary and stop — nothing partial to clean up (the attachment step summary and stop — nothing partial to clean up (the attachment step
@@ -110,17 +197,22 @@ only runs after successful creation).
## Step 7 — Attach screenshot ## 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 \ curl -s -o /tmp/gw-triage-attach.json -w "%{http_code}" -X POST \
-H "X-Atlassian-Token: no-check" \ -H "X-Atlassian-Token: no-check" \
-u "$JIRA_EMAIL:$JIRA_API_TOKEN" \ --netrc-file ~/.config/gw-triage/netrc \
-F "file=@<screenshot-path>" \ -F "file=@<screenshot-path>" \
"<site>/rest/api/3/issue/<ISSUE-KEY>/attachments" "<site>/rest/api/3/issue/<ISSUE-KEY>/attachments"
`<site>` comes from routing.json. Success = HTTP 200. Any failure is If Step 0 answered `env` (legacy install, no netrc), replace the
non-fatal: tell the user (Italian) to drag the image into the Jira `--netrc-file` line with `-u "$JIRA_EMAIL:$JIRA_API_TOKEN"`, leaving
issue manually. 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 ## Step 8 — Report