Compare commits
8 Commits
a0219520bf
...
29d0b1990d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29d0b1990d | ||
|
|
f99666bf8a | ||
|
|
bf92d05df2 | ||
|
|
79834fee3f | ||
|
|
6525f60f86 | ||
|
|
ec853559af | ||
|
|
a7dcc361c0 | ||
|
|
a967f5c38e |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gw-triage",
|
||||
"description": "Da screenshot + messaggio Telegram a issue Jira instradata al dev giusto",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"author": {
|
||||
"name": "GrowingWay"
|
||||
}
|
||||
|
||||
59
README.md
59
README.md
@@ -5,6 +5,8 @@ assegnata al dev giusto.
|
||||
|
||||
## Installazione (una volta sola)
|
||||
|
||||
### Claude Code
|
||||
|
||||
1. **Plugin Atlassian** — in Claude Code:
|
||||
`/plugin install atlassian@claude-plugins-official`
|
||||
2. **Login Atlassian** — esegui `/mcp`, seleziona `atlassian` e completa
|
||||
@@ -16,27 +18,45 @@ assegnata al dev giusto.
|
||||
4. **Token API** (per allegare gli screenshot — facoltativo ma
|
||||
consigliato): esegui `/gw-triage:setup` e segui le istruzioni.
|
||||
|
||||
### Codex CLI
|
||||
|
||||
1. Clona il repo dove preferisci:
|
||||
`git clone https://git.growingway.com/giuse/gw-triage.git`
|
||||
2. Dalla cartella clonata esegui `./install-codex.sh` — crea i link
|
||||
alle skill in `~/.agents/skills/`. Nota: le skill si chiamano
|
||||
`triage`, `setup` e `map-repo`; se hai già altre skill con questi
|
||||
nomi entrano in conflitto.
|
||||
3. **Token API** (qui obbligatorio — su Codex tutte le chiamate Jira
|
||||
lo usano): invoca `$setup` e segui le istruzioni.
|
||||
|
||||
Per aggiornare: `git pull` nella cartella clonata (i link restano
|
||||
validi). Su Claude Code: `/plugin marketplace update gw-triage`.
|
||||
|
||||
## Token API Jira
|
||||
|
||||
Serve solo ad allegare gli screenshot alle issue (l'MCP Atlassian non
|
||||
supporta gli allegati). Senza token tutto funziona lo stesso: viene
|
||||
saltato solo l'allegato.
|
||||
Su Claude Code serve solo ad allegare gli screenshot alle issue (le
|
||||
altre operazioni passano dall'MCP Atlassian): senza token tutto
|
||||
funziona lo stesso, viene saltato solo l'allegato. Su Codex invece è
|
||||
obbligatorio: tutte le chiamate Jira lo usano.
|
||||
|
||||
Esegui `/gw-triage:setup` in Claude Code: ti guida nella creazione del
|
||||
token dalla pagina Atlassian, te lo chiede, lo verifica e lo salva da
|
||||
solo. Niente configurazione manuale della shell.
|
||||
Esegui il setup (`/gw-triage:setup` su Claude Code, `$setup` su
|
||||
Codex): ti guida nella creazione del token dalla pagina Atlassian, te
|
||||
lo chiede, lo verifica e lo salva in `~/.config/gw-triage/netrc`
|
||||
(valido da subito, senza riavviare nulla). Se avevi già configurato il
|
||||
token in `~/.claude/settings.json`, il setup lo migra da solo.
|
||||
|
||||
⚠️ Il token agisce a tuo nome su Jira: non condividerlo. Se trapela,
|
||||
revocalo da <https://id.atlassian.com/manage-profile/security/api-tokens>.
|
||||
Quando scade, `/gw-triage:triage` continua a funzionare — salta solo
|
||||
l'allegato: rilancia `/gw-triage:setup` per sostituirlo.
|
||||
Quando scade: su Claude Code `/gw-triage:triage` continua a funzionare
|
||||
(salta solo l'allegato), su Codex si ferma e ti rimanda al setup.
|
||||
Rilancia il setup per sostituirlo.
|
||||
|
||||
## Uso quotidiano
|
||||
|
||||
1. In Claude Code allega uno screenshot (**trascina il file nel
|
||||
prompt**, così può essere allegato alla issue) e/o scrivi una breve
|
||||
descrizione del problema, sufficiente a identificarlo, poi invoca
|
||||
`/gw-triage:triage`.
|
||||
1. Allega uno screenshot (**trascina il file nel prompt**, così può
|
||||
essere allegato alla issue) e/o scrivi una breve descrizione del
|
||||
problema, sufficiente a identificarlo, poi invoca
|
||||
`/gw-triage:triage` (Claude Code) o `$triage` (Codex).
|
||||
2. Rispondi all'eventuale domanda di chiarimento, conferma la bozza →
|
||||
la issue viene creata e ricevi il link.
|
||||
|
||||
@@ -46,15 +66,20 @@ l'allegato va poi trascinato in Jira a mano.
|
||||
## Aggiornare la conoscenza dei repo
|
||||
|
||||
Quando la tua codebase cambia in modo visibile agli utenti, dalla
|
||||
cartella del repo esegui `/gw-triage:map-repo` e segui le istruzioni:
|
||||
cartella del repo esegui `/gw-triage:map-repo` (Claude Code) o
|
||||
`$map-repo` (Codex) e segui le istruzioni:
|
||||
il profilo aggiornato viene pushato qui e gli altri lo ricevono con
|
||||
`/plugin marketplace update gw-triage`.
|
||||
`/plugin marketplace update gw-triage` (Claude Code) o `git pull`
|
||||
nella cartella clonata (Codex).
|
||||
|
||||
## Problemi comuni
|
||||
|
||||
- **"MCP Atlassian non disponibile"** → passi 1–2 dell'installazione.
|
||||
- **"Allegato saltato"** → esegui `/gw-triage:setup` (token mancante,
|
||||
scaduto o sessione da riavviare).
|
||||
- **"MCP Atlassian non disponibile"** → passi 1–2 dell'installazione
|
||||
Claude Code.
|
||||
- **"Allegato saltato"** → esegui il setup (token mancante, scaduto o
|
||||
revocato).
|
||||
- **Su Codex le skill non compaiono** → riesegui `./install-codex.sh`
|
||||
dalla cartella clonata e controlla i link in `~/.agents/skills/`.
|
||||
- **La issue finisce nell'epic sbagliata** → correggi in Jira e apri
|
||||
una issue su questo repo per aggiustare `config/routing.json` o il
|
||||
profilo in `knowledge/`.
|
||||
|
||||
172
docs/codex-support-design.md
Normal file
172
docs/codex-support-design.md
Normal file
@@ -0,0 +1,172 @@
|
||||
# gw-triage — Codex CLI support
|
||||
|
||||
Date: 2026-07-10
|
||||
Status: approved
|
||||
|
||||
## Problem
|
||||
|
||||
The plugin only runs under Claude Code: distribution relies on the
|
||||
Claude plugin marketplace, skills locate their data via
|
||||
`${CLAUDE_PLUGIN_ROOT}`, Jira access goes through the Atlassian MCP
|
||||
plugin, and credentials live in the `env` block of
|
||||
`~/.claude/settings.json`. Teammates on OpenAI Codex CLI can't use any
|
||||
of it. Goal: full parity — `triage`, `setup`, and `map-repo` all work
|
||||
on Codex, from the same repo, with no duplicated skill files.
|
||||
|
||||
## Decisions (agreed 2026-07-10)
|
||||
|
||||
1. **Scope**: full parity for all three skills.
|
||||
2. **Jira transport on Codex**: plain REST via curl with the Jira API
|
||||
token. No MCP configuration on Codex. Claude Code keeps its MCP
|
||||
path unchanged.
|
||||
3. **Skill files**: one SKILL.md per skill, shared by both platforms,
|
||||
branching internally where behavior differs.
|
||||
4. **Credentials**: a single netrc file at `~/.config/gw-triage/netrc`
|
||||
used by curl on both platforms, replacing the settings.json env
|
||||
block as the primary store.
|
||||
|
||||
## Verified platform facts
|
||||
|
||||
- Codex discovers skills in `.agents/skills` (project, walking up to
|
||||
repo root) and `~/.agents/skills` (user level). Symlinked skill
|
||||
directories are followed.
|
||||
- Skills use the same SKILL.md format (frontmatter `name` +
|
||||
`description`); invoked explicitly as `$<name>` or implicitly via
|
||||
the description.
|
||||
- Codex's `[shell_environment_policy]` env injection filters names
|
||||
containing `TOKEN` by default and has open reliability issues —
|
||||
ruled out in favor of the netrc file.
|
||||
- Jira Cloud REST API v2 (`/rest/api/2/…`) is still served and accepts
|
||||
plain-text descriptions, avoiding the ADF JSON required by v3
|
||||
`createIssue`. v2 is legacy; if Atlassian retires it, the REST-mode
|
||||
steps move to v3 + minimal ADF paragraphs.
|
||||
|
||||
## Design
|
||||
|
||||
### 1. Distribution
|
||||
|
||||
Repo structure unchanged. Codex users clone the repo anywhere and
|
||||
symlink each skill directory into `~/.agents/skills/`:
|
||||
|
||||
~/.agents/skills/triage -> <clone>/skills/triage
|
||||
~/.agents/skills/setup -> <clone>/skills/setup
|
||||
~/.agents/skills/map-repo -> <clone>/skills/map-repo
|
||||
|
||||
A small `install-codex.sh` at the repo root creates/refreshes the
|
||||
symlinks idempotently. Updates arrive with `git pull` in the clone.
|
||||
|
||||
Skill names stay as-is so Claude Code commands don't change
|
||||
(`/gw-triage:triage`). On Codex they are `$triage`, `$setup`,
|
||||
`$map-repo`; the generic names could collide with other installed
|
||||
skills — accepted risk for a three-person team, noted in the README.
|
||||
|
||||
### 2. Platform detection and root resolution
|
||||
|
||||
Each SKILL.md gets a short "Environment" preamble:
|
||||
|
||||
- **Root**: `${CLAUDE_PLUGIN_ROOT}` if set; otherwise resolve the real
|
||||
path (symlinks followed) of the skill's own directory and go up two
|
||||
levels. `config/` and `knowledge/` are addressed relative to that
|
||||
root everywhere.
|
||||
- **Mode** (triage only): Atlassian MCP tools available → MCP mode
|
||||
(today's behavior, unchanged); otherwise → REST mode.
|
||||
|
||||
### 3. Credentials — netrc file
|
||||
|
||||
`setup` writes `~/.config/gw-triage/netrc`:
|
||||
|
||||
machine growingway.atlassian.net
|
||||
login <email>
|
||||
password <token>
|
||||
|
||||
(machine host derived from `site` in routing.json), `chmod 600`. Every
|
||||
curl call on both platforms passes `--netrc-file
|
||||
~/.config/gw-triage/netrc`, read at call time — no session restart
|
||||
needed after setup, and no secrets on command lines or in process
|
||||
listings.
|
||||
|
||||
`setup` itself becomes platform-neutral (file operations + curl only):
|
||||
|
||||
- Verify pasted credentials against `GET /rest/api/2/myself` before
|
||||
saving (3-attempt limit, network-vs-auth error distinction — as
|
||||
today).
|
||||
- **Migration**: if credentials already exist in the session env or in
|
||||
`~/.claude/settings.json` `env`, verify them and migrate them into
|
||||
the netrc automatically; suggest removing the settings.json entries
|
||||
(leftover shell-profile check stays).
|
||||
- The temp-netrc-for-literals dance disappears: the real netrc file IS
|
||||
the store, written before verification and deleted only if
|
||||
verification ultimately fails.
|
||||
|
||||
`triage` reads the netrc as the primary credential source and falls
|
||||
back to `JIRA_EMAIL`/`JIRA_API_TOKEN` env vars (legacy installs) for
|
||||
the attachment step.
|
||||
|
||||
### 4. Triage in REST mode
|
||||
|
||||
Used on Codex. (Claude Code without MCP still stops and points at the
|
||||
Atlassian plugin install, as today — MCP remains the intended path
|
||||
there.)
|
||||
|
||||
On Codex the token is **required** — it is the only transport. Missing
|
||||
or invalid netrc → stop with `$setup` instructions.
|
||||
|
||||
| Step | MCP mode (unchanged) | REST mode |
|
||||
|---|---|---|
|
||||
| Preflight | `getAccessibleAtlassianResources` | `GET /rest/api/2/myself` → expect 200 |
|
||||
| Duplicate search | `searchJiraIssuesUsingJql` | `GET /rest/api/3/search/jql?jql=<urlencoded>` (the v2/v3 `/search` endpoints were removed by Atlassian in 2025) |
|
||||
| Create | `createJiraIssue` | `POST /rest/api/2/issue` (JSON body: project, issuetype, summary, plain-text description, assignee accountId, parent epic) |
|
||||
| Comment on duplicate | `addCommentToJiraIssue` | `POST /rest/api/2/issue/{key}/comment` |
|
||||
| Attach screenshot | curl (as today) | same curl, `--netrc-file` |
|
||||
|
||||
`cloudId` in routing.json becomes MCP-only; REST mode uses `site`.
|
||||
Classification, drafting, confirmation flow, and Italian interaction
|
||||
are identical in both modes.
|
||||
|
||||
### 5. map-repo
|
||||
|
||||
Two touch-ups:
|
||||
|
||||
- Root resolution per §2 (replaces `${CLAUDE_PLUGIN_ROOT}`).
|
||||
- Survey step: "dispatch one exploration subagent **if the platform
|
||||
supports subagent dispatch; otherwise perform the survey yourself**,
|
||||
covering the same six points."
|
||||
- Publish step: note that Codex teammates receive updates with
|
||||
`git pull` in their clone (Claude Code users keep
|
||||
`/plugin marketplace update gw-triage`).
|
||||
|
||||
### 6. README
|
||||
|
||||
- New "Installazione (Codex)" section: clone, `./install-codex.sh`,
|
||||
run `$setup`, daily use via `$triage`.
|
||||
- Token section updated: netrc path, token optional on Claude Code
|
||||
(attachments only), **required** on Codex.
|
||||
- Per-platform update instructions and troubleshooting entries.
|
||||
|
||||
## Error handling
|
||||
|
||||
- REST calls: treat non-2xx as failure; show the raw body with a
|
||||
one-line Italian summary. Create-issue failure stops before the
|
||||
attachment step (nothing partial), as today.
|
||||
- Netrc unreadable/missing on Codex → stop with setup guidance; on
|
||||
Claude Code → warn once that attachment will be skipped, proceed.
|
||||
- JQL must be URL-encoded in REST mode (curl `--data-urlencode` with
|
||||
`-G`).
|
||||
|
||||
## Testing
|
||||
|
||||
- REST commands exercised directly against Jira: `myself`, JQL search,
|
||||
create on a throwaway issue, comment, attachment — then delete the
|
||||
throwaway.
|
||||
- Codex smoke test: skills discovered after `install-codex.sh`,
|
||||
`$triage` dry run reaches the draft step, `$setup` full run.
|
||||
- Claude Code regression: `/gw-triage:triage` full run with netrc in
|
||||
place (MCP mode + netrc attachment), `/gw-triage:setup` migration
|
||||
path from settings.json env vars.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Renaming skills or namespacing for Codex.
|
||||
- Moving Claude Code off MCP.
|
||||
- Windows support (team is on macOS).
|
||||
- v3/ADF migration (documented as future work if v2 is retired).
|
||||
773
docs/codex-support-plan.md
Normal file
773
docs/codex-support-plan.md
Normal file
@@ -0,0 +1,773 @@
|
||||
# Codex CLI Support Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Make the gw-triage skills (triage, setup, map-repo) work under OpenAI Codex CLI with full parity, from the same repo, without breaking the Claude Code flow.
|
||||
|
||||
**Architecture:** Shared SKILL.md files that resolve their root via `${CLAUDE_PLUGIN_ROOT}` or their own real path, branch between Atlassian MCP (Claude Code) and Jira REST v2 via curl (Codex), and read credentials from a single netrc file at `~/.config/gw-triage/netrc` written by the setup skill. Codex installation = clone + symlinks into `~/.agents/skills/` created by `install-codex.sh`.
|
||||
|
||||
**Tech Stack:** SKILL.md (Agent Skills spec), POSIX sh, curl, Jira Cloud REST API v2.
|
||||
|
||||
**Spec:** `docs/codex-support-design.md` (approved 2026-07-10).
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- All user interaction in the skills happens in Italian; SKILL.md prose stays in English.
|
||||
- Never put a literal token on a shell command line or in a reply; credentials move only via files (netrc, mode 600) or unexpanded `$VAR` references.
|
||||
- Netrc path is exactly `~/.config/gw-triage/netrc`. Codex skills dir is exactly `~/.agents/skills`.
|
||||
- Jira REST calls use API v2 (`/rest/api/2/…`) except attachments (`/rest/api/3/issue/<KEY>/attachments`) and JQL search (`/rest/api/3/search/jql` — the v2 search endpoint was removed by Atlassian in 2025).
|
||||
- On Claude Code without MCP, triage STOPS with the install guide — REST mode is not a fallback there.
|
||||
- On Codex the token is REQUIRED; on Claude Code it remains optional (attachments only).
|
||||
- Skill frontmatter `name:` values must not change (`triage`, `setup`, `map-repo`) — they define the Claude Code commands.
|
||||
- Claude Code MCP behavior in triage is unchanged: same tools, same cloudId usage.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: `install-codex.sh`
|
||||
|
||||
**Files:**
|
||||
- Create: `install-codex.sh` (repo root, executable)
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: idempotent script that symlinks `skills/{triage,setup,map-repo}` into `~/.agents/skills/`. README (Task 5) references it as `./install-codex.sh`.
|
||||
|
||||
- [ ] **Step 1: Write the script**
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
# Install the gw-triage skills for OpenAI Codex CLI by symlinking them
|
||||
# into ~/.agents/skills. Safe to re-run; updates arrive via `git pull`
|
||||
# in this clone (symlinks keep pointing at the updated files).
|
||||
set -eu
|
||||
|
||||
repo_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
|
||||
dest="${HOME}/.agents/skills"
|
||||
|
||||
mkdir -p "$dest"
|
||||
for skill in triage setup map-repo; do
|
||||
ln -sfn "$repo_dir/skills/$skill" "$dest/$skill"
|
||||
echo "linked $dest/$skill -> $repo_dir/skills/$skill"
|
||||
done
|
||||
|
||||
echo "Fatto. Per aggiornare in futuro: git -C \"$repo_dir\" pull"
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Make it executable and verify against a scratch HOME**
|
||||
|
||||
Run (fish syntax, since the user shell is fish; use `bash -c` to keep it portable):
|
||||
|
||||
```bash
|
||||
chmod +x install-codex.sh
|
||||
bash -c 'HOME=$(mktemp -d) && ./install-codex.sh && ls -l "$HOME/.agents/skills" && readlink "$HOME/.agents/skills/triage"'
|
||||
```
|
||||
|
||||
Expected: three `linked …` lines, `ls` shows `map-repo`, `setup`, `triage` as symlinks, `readlink` prints `<repo>/skills/triage`. Re-run the script against the same HOME to confirm idempotency (no error, same links).
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add install-codex.sh
|
||||
git commit -m "feat: add Codex CLI installer (symlinks into ~/.agents/skills)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Rewrite `skills/setup/SKILL.md` for the shared netrc store
|
||||
|
||||
**Files:**
|
||||
- Modify: `skills/setup/SKILL.md` (full rewrite of the body; frontmatter `name` unchanged)
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: credentials at `~/.config/gw-triage/netrc` in the format `machine <host>` / `login <email>` / `password <token>`, mode 600. Task 3 (triage) consumes this file via `curl --netrc-file`.
|
||||
|
||||
- [ ] **Step 1: Replace the file content**
|
||||
|
||||
Write `skills/setup/SKILL.md` with exactly:
|
||||
|
||||
````markdown
|
||||
---
|
||||
name: setup
|
||||
description: Use when configuring the Jira API credentials for gw-triage — first-time setup, an "allegato saltato" warning from triage, missing or expired credentials, or replacing a revoked token. Triggers on /gw-triage:setup, $setup, "configura il token", "gli allegati non funzionano".
|
||||
---
|
||||
|
||||
# Setup — token API Jira guidato
|
||||
|
||||
You guide the user through creating a Jira API token and storing it in
|
||||
the gw-triage netrc file. The `triage` skill reads that file for its
|
||||
REST calls: screenshot attachments on every platform, plus search /
|
||||
create / comment when running under Codex.
|
||||
|
||||
**All interaction with the user happens in Italian.** This file is
|
||||
English for precision; never quote it to the user.
|
||||
|
||||
## 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.
|
||||
- **Store**: `~/.config/gw-triage/netrc`, mode 600. curl reads it at
|
||||
call time on every platform, so changes take effect immediately — no
|
||||
session restart, no shell configuration.
|
||||
- **Host**: the `site` value in `<root>/config/routing.json` without
|
||||
the scheme (e.g. `growingway.atlassian.net`).
|
||||
|
||||
**Keep the token out of replies and displayed commands.** Refer to it
|
||||
as "il token" and never repeat its value. Never inline a literal token
|
||||
on a shell command line — it ends up in the transcript and the process
|
||||
list. Write credentials into the netrc file with the file-writing
|
||||
tool, then let curl read them via `--netrc-file`.
|
||||
|
||||
The verification call used throughout:
|
||||
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
--netrc-file ~/.config/gw-triage/netrc \
|
||||
https://<host>/rest/api/2/myself
|
||||
|
||||
## Step 0 — Check existing configuration
|
||||
|
||||
1. If `~/.config/gw-triage/netrc` exists and is readable, run the
|
||||
verification call.
|
||||
- `200` → tell the user (Italian) the token already works and ask
|
||||
whether they want to replace it anyway. If not, stop.
|
||||
- anything else → tell them the stored token no longer works
|
||||
(probably expired or revoked) and continue to Step 1.
|
||||
2. Otherwise look for legacy credentials, in order:
|
||||
- session env: `test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo session || echo unset`
|
||||
- `~/.claude/settings.json` (if it exists): `env.JIRA_EMAIL` /
|
||||
`env.JIRA_API_TOKEN`.
|
||||
|
||||
If found in either place: write them to the netrc (Step 2 format,
|
||||
chmod 600) and run the verification call.
|
||||
- `200` → tell the user (Italian) the existing credentials were
|
||||
migrated to the new store and work immediately; then do Step 3
|
||||
(clean up legacy stores) and Step 4. Done — skip token creation.
|
||||
- anything else → delete the netrc just written, tell them the old
|
||||
token no longer works, continue to Step 1.
|
||||
3. Nothing found → first-time setup, continue to Step 1.
|
||||
|
||||
## Step 1 — Token creation (user, in the browser)
|
||||
|
||||
Print in Italian, compactly:
|
||||
|
||||
1. Apri <https://id.atlassian.com/manage-profile/security/api-tokens>
|
||||
(login con l'account Atlassian aziendale).
|
||||
2. **Create API token** → nome `gw-triage` → scegli la scadenza →
|
||||
**copia subito il token** (viene mostrato una volta sola).
|
||||
3. Incolla qui email aziendale e token (vanno bene anche su due righe).
|
||||
|
||||
Add one line: il token verrà salvato in chiaro in
|
||||
`~/.config/gw-triage/netrc` sul suo computer, quindi non condividere né
|
||||
il file né questa conversazione.
|
||||
|
||||
End the turn and wait. If the reply contains only one of the two
|
||||
values, ask for the missing one. If the user can't create the token
|
||||
(no permission, page unreachable), stop and suggest asking whoever
|
||||
manages the Atlassian accounts.
|
||||
|
||||
## Step 2 — Save, then verify
|
||||
|
||||
1. Create `~/.config/gw-triage/` if missing. Write the netrc file with
|
||||
the file-writing tool:
|
||||
|
||||
machine <host>
|
||||
login <email>
|
||||
password <token>
|
||||
|
||||
Then `chmod 600 ~/.config/gw-triage/netrc`.
|
||||
2. Run the verification call.
|
||||
- `200` → Step 3.
|
||||
- `401`/`403` → wrong email or token (a common cause: copied with a
|
||||
trailing space or truncated). Ask the user to re-copy and
|
||||
re-paste, rewrite the file, verify again; after the third failed
|
||||
verification overall, delete the netrc file, stop, and suggest
|
||||
creating a fresh token.
|
||||
- Anything else (timeout, DNS) → network problem, not credentials:
|
||||
report it and stop. Leave the netrc in place — it may verify fine
|
||||
later.
|
||||
|
||||
## Step 3 — Clean up legacy stores
|
||||
|
||||
1. `~/.claude/settings.json`: if it exists and has `env.JIRA_EMAIL` /
|
||||
`env.JIRA_API_TOKEN`, offer (Italian) to remove those two keys —
|
||||
with the file tools (Read + Edit), never shell text-mangling, and
|
||||
preserving every other key. If the file is invalid JSON, don't
|
||||
touch it; just tell the user it should be cleaned up by hand.
|
||||
2. Shell profiles: run
|
||||
`fish -c 'set -U' 2>/dev/null | grep -i jira` and
|
||||
`grep -l JIRA_API_TOKEN ~/.config/fish/config.fish ~/.config/fish/conf.d/*.fish ~/.zshrc ~/.bashrc ~/.zprofile ~/.profile 2>/dev/null`.
|
||||
If anything turns up, tell the user (Italian) to remove it so it
|
||||
can't shadow the netrc (fish: `set -e JIRA_EMAIL; set -e
|
||||
JIRA_API_TOKEN`; altrimenti togliere gli `export` dal file
|
||||
indicato).
|
||||
|
||||
## Step 4 — Report
|
||||
|
||||
In Italian: token verificato e salvato in `~/.config/gw-triage/netrc`.
|
||||
Vale da subito, anche nelle sessioni già aperte. Per sostituirlo o dopo
|
||||
una revoca basta rilanciare il setup: `/gw-triage:setup` su Claude
|
||||
Code, `$setup` su Codex.
|
||||
````
|
||||
|
||||
- [ ] **Step 2: Verify the file**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
head -4 skills/setup/SKILL.md
|
||||
grep -c 'netrc-file' skills/setup/SKILL.md
|
||||
grep -n 'settings.json' skills/setup/SKILL.md
|
||||
```
|
||||
|
||||
Expected: frontmatter intact with `name: setup`; `netrc-file` appears ≥1 time; `settings.json` appears only in migration/cleanup contexts (Step 0.2 and Step 3.1), never as the store.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add skills/setup/SKILL.md
|
||||
git commit -m "feat(setup): store credentials in shared netrc, migrate legacy env vars"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Rewrite `skills/triage/SKILL.md` with MCP/REST dual mode
|
||||
|
||||
**Files:**
|
||||
- Modify: `skills/triage/SKILL.md` (full rewrite; frontmatter `name` unchanged)
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `~/.config/gw-triage/netrc` (Task 2 format) for REST mode and attachments.
|
||||
- Produces: nothing consumed by other tasks; README (Task 5) references `$triage` invocation on Codex.
|
||||
|
||||
- [ ] **Step 1: Replace the file content**
|
||||
|
||||
Write `skills/triage/SKILL.md` with exactly:
|
||||
|
||||
````markdown
|
||||
---
|
||||
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, $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
|
||||
|
||||
You convert an informal report (screenshot + short message) into a
|
||||
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.
|
||||
|
||||
## 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`. `<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
|
||||
|
||||
**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. 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 \
|
||||
<site>/rest/api/2/myself
|
||||
|
||||
Anything but `200` → STOP (Italian): token scaduto o revocato,
|
||||
rilancia `$setup`.
|
||||
|
||||
## Step 1 — Input
|
||||
|
||||
Expect a short message (usually Italian) and optionally a screenshot.
|
||||
- Screenshot given as a file path (dragged into the prompt): Read it
|
||||
for analysis and keep the path for Step 7.
|
||||
- Pasted image (no path): analyze it; warn (Italian) that the
|
||||
attachment will be skipped — it can be dragged into Jira manually.
|
||||
- No screenshot: proceed on the text alone.
|
||||
- Neither message nor screenshot: ask (Italian) for at least one.
|
||||
|
||||
## Step 2 — Load routing and knowledge
|
||||
|
||||
Read `<root>/config/routing.json` and every `.md` file in
|
||||
`<root>/knowledge/` except `README.md`.
|
||||
|
||||
## Step 3 — Classify
|
||||
|
||||
Decide, using the knowledge profiles (error fingerprints, symptom
|
||||
heuristics, glossaries, "not mine" sections):
|
||||
- **type**: `Bug` (something broken) or `Task` (feature request /
|
||||
change / improvement)
|
||||
- **area**: exactly one key from `routing.json` `areas`.
|
||||
|
||||
Platform rules for app issues: visible Android UI or device →
|
||||
`app-android`; visible iOS UI or device → `app-ios`; app issue with no
|
||||
platform signal → `app-shared`.
|
||||
|
||||
If genuinely uncertain between two areas, ask the user ONE targeted
|
||||
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.
|
||||
|
||||
## Step 4 — Duplicate check
|
||||
|
||||
Extract 2–4 distinctive keywords (include Italian and English variants
|
||||
of domain terms). Search with JQL
|
||||
`project = <projectKey> AND text ~ "<keywords>" AND statusCategory != Done ORDER BY created DESC`
|
||||
(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
|
||||
(Italian) whether to comment on it instead of creating a new issue.
|
||||
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": "<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)
|
||||
|
||||
Build and present:
|
||||
- **Titolo**: concise imperative, e.g. "Correggere overflow nella
|
||||
schermata prenotazioni su Android".
|
||||
- **Descrizione** with sections:
|
||||
- *Contesto* — source of the report (chat Telegram, date, reporter
|
||||
if known)
|
||||
- *Passi per riprodurre* — inferred from screenshot/message; mark
|
||||
inferred steps explicitly ("(dedotto dallo screenshot)")
|
||||
- *Comportamento atteso / osservato*
|
||||
- *Screenshot* — one line describing what it shows
|
||||
- **Tipo**: Bug or Task. **Epic**: from routing area. **Assegnatario**:
|
||||
from routing area.
|
||||
|
||||
Show the complete draft and ask ONE confirmation (sì / correggi …).
|
||||
Apply corrections; re-confirm only if the area changed (it changes
|
||||
epic and assignee).
|
||||
|
||||
## Step 6 — Create
|
||||
|
||||
- MCP mode: call `createJiraIssue` with `cloudId`, `projectKey`,
|
||||
`issueTypeName` (`Bug` or `Task`), `summary`, `description`, the
|
||||
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
|
||||
summary and stop — nothing partial to clean up (the attachment step
|
||||
only runs after successful creation).
|
||||
|
||||
## Step 7 — Attach screenshot
|
||||
|
||||
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" \
|
||||
--netrc-file ~/.config/gw-triage/netrc \
|
||||
-F "file=@<screenshot-path>" \
|
||||
"<site>/rest/api/3/issue/<ISSUE-KEY>/attachments"
|
||||
|
||||
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
|
||||
|
||||
Print in Italian: issue key with link `<site>/browse/<KEY>`, type,
|
||||
epic, assignee, and whether the screenshot was attached.
|
||||
````
|
||||
|
||||
- [ ] **Step 2: Verify the file**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
head -4 skills/triage/SKILL.md
|
||||
grep -c 'REST mode' skills/triage/SKILL.md
|
||||
grep -n 'CLAUDE_PLUGIN_ROOT' skills/triage/SKILL.md
|
||||
grep -n 'rest/api/3' skills/triage/SKILL.md
|
||||
```
|
||||
|
||||
Expected: frontmatter intact with `name: triage`; `REST mode` appears in Environment and Steps 0/4/6; `CLAUDE_PLUGIN_ROOT` appears only in the Environment root/mode rules (not as a hardcoded path elsewhere); the only v3 URLs are the attachments endpoint and `search/jql`.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add skills/triage/SKILL.md
|
||||
git commit -m "feat(triage): dual MCP/REST mode with shared netrc credentials"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Update `skills/map-repo/SKILL.md`
|
||||
|
||||
**Files:**
|
||||
- Modify: `skills/map-repo/SKILL.md` (three targeted edits)
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: root-resolution convention from Tasks 2–3 (same preamble wording).
|
||||
|
||||
- [ ] **Step 1: Update frontmatter description**
|
||||
|
||||
Replace:
|
||||
|
||||
```
|
||||
description: Use when generating or refreshing a codebase's triage profile for the gw-triage plugin — run from inside the repo to map. Triggers on /map-repo, "mappa questo repo", "aggiorna il profilo di triage".
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```
|
||||
description: Use when generating or refreshing a codebase's triage profile for the gw-triage plugin — run from inside the repo to map. Triggers on /gw-triage:map-repo, $map-repo, "mappa questo repo", "aggiorna il profilo di triage".
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add the Environment section and fix root references**
|
||||
|
||||
After the paragraph ending "(it is read by the triage model, not by humans).", insert:
|
||||
|
||||
```markdown
|
||||
## 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. Paths below marked `<root>` are
|
||||
relative to it.
|
||||
```
|
||||
|
||||
Then replace `${CLAUDE_PLUGIN_ROOT}/knowledge/README.md` with `<root>/knowledge/README.md` (Step 2) and `${CLAUDE_PLUGIN_ROOT}` with `<root>` in Step 4's remote-URL instruction.
|
||||
|
||||
- [ ] **Step 3: Make the survey subagent optional**
|
||||
|
||||
Replace:
|
||||
|
||||
```
|
||||
Dispatch ONE exploration subagent with this prompt, filling <repo-path>:
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```
|
||||
If the platform supports dispatching subagents, dispatch ONE
|
||||
exploration subagent with the prompt below, filling <repo-path>;
|
||||
otherwise perform the same survey yourself, covering all six points
|
||||
before writing anything:
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Mention the Codex update path in Step 4 of the skill**
|
||||
|
||||
Replace:
|
||||
|
||||
```
|
||||
4. Tell the user (Italian) that teammates receive the update with
|
||||
`/plugin marketplace update gw-triage`.
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
```
|
||||
4. Tell the user (Italian) that teammates receive the update with
|
||||
`/plugin marketplace update gw-triage` on Claude Code, or with
|
||||
`git pull` in their gw-triage clone on Codex.
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Verify and commit**
|
||||
|
||||
```bash
|
||||
grep -c 'CLAUDE_PLUGIN_ROOT' skills/map-repo/SKILL.md
|
||||
grep -n '<root>' skills/map-repo/SKILL.md
|
||||
git add skills/map-repo/SKILL.md
|
||||
git commit -m "feat(map-repo): platform-neutral root resolution and survey"
|
||||
```
|
||||
|
||||
Expected: `CLAUDE_PLUGIN_ROOT` count is 1 (the Environment section only); `<root>` appears in Steps 2 and 4.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: README + version bump
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `.claude-plugin/plugin.json` (version `0.2.0` → `0.3.0`)
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `./install-codex.sh` (Task 1), netrc store (Task 2), `$triage`/`$setup` invocations (Tasks 2–3).
|
||||
|
||||
- [ ] **Step 1: Restructure the installation section**
|
||||
|
||||
Replace the `## Installazione (una volta sola)` section with:
|
||||
|
||||
```markdown
|
||||
## Installazione (una volta sola)
|
||||
|
||||
### Claude Code
|
||||
|
||||
1. **Plugin Atlassian** — in Claude Code:
|
||||
`/plugin install atlassian@claude-plugins-official`
|
||||
2. **Login Atlassian** — esegui `/mcp`, seleziona `atlassian` e completa
|
||||
il login nel browser con l'account aziendale. Verifica che risulti
|
||||
*connected*.
|
||||
3. **Installa gw-triage**:
|
||||
`/plugin marketplace add https://git.growingway.com/giuse/gw-triage.git`
|
||||
`/plugin install gw-triage`
|
||||
4. **Token API** (per allegare gli screenshot — facoltativo ma
|
||||
consigliato): esegui `/gw-triage:setup` e segui le istruzioni.
|
||||
|
||||
### Codex CLI
|
||||
|
||||
1. Clona il repo dove preferisci:
|
||||
`git clone https://git.growingway.com/giuse/gw-triage.git`
|
||||
2. Dalla cartella clonata esegui `./install-codex.sh` — crea i link
|
||||
alle skill in `~/.agents/skills/`. Nota: le skill si chiamano
|
||||
`triage`, `setup` e `map-repo`; se hai già altre skill con questi
|
||||
nomi entrano in conflitto.
|
||||
3. **Token API** (qui obbligatorio — su Codex tutte le chiamate Jira
|
||||
lo usano): invoca `$setup` e segui le istruzioni.
|
||||
|
||||
Per aggiornare: `git pull` nella cartella clonata (i link restano
|
||||
validi). Su Claude Code: `/plugin marketplace update gw-triage`.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Update the token section**
|
||||
|
||||
Replace the `## Token API Jira` section with:
|
||||
|
||||
```markdown
|
||||
## Token API Jira
|
||||
|
||||
Su Claude Code serve solo ad allegare gli screenshot alle issue (le
|
||||
altre operazioni passano dall'MCP Atlassian): senza token tutto
|
||||
funziona lo stesso, viene saltato solo l'allegato. Su Codex invece è
|
||||
obbligatorio: tutte le chiamate Jira lo usano.
|
||||
|
||||
Esegui il setup (`/gw-triage:setup` su Claude Code, `$setup` su
|
||||
Codex): ti guida nella creazione del token dalla pagina Atlassian, te
|
||||
lo chiede, lo verifica e lo salva in `~/.config/gw-triage/netrc`
|
||||
(valido da subito, senza riavviare nulla). Se avevi già configurato il
|
||||
token in `~/.claude/settings.json`, il setup lo migra da solo.
|
||||
|
||||
⚠️ Il token agisce a tuo nome su Jira: non condividerlo. Se trapela,
|
||||
revocalo da <https://id.atlassian.com/manage-profile/security/api-tokens>.
|
||||
Quando scade: su Claude Code `/gw-triage:triage` continua a funzionare
|
||||
(salta solo l'allegato), su Codex si ferma e ti rimanda al setup.
|
||||
Rilancia il setup per sostituirlo.
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Update daily use and troubleshooting**
|
||||
|
||||
In `## Uso quotidiano`, change step 1 to mention both invocations:
|
||||
|
||||
```markdown
|
||||
1. Allega uno screenshot (**trascina il file nel prompt**, così può
|
||||
essere allegato alla issue) e/o scrivi una breve descrizione del
|
||||
problema, sufficiente a identificarlo, poi invoca
|
||||
`/gw-triage:triage` (Claude Code) o `$triage` (Codex).
|
||||
```
|
||||
|
||||
In `## Aggiornare la conoscenza dei repo`, replace the closing sentence
|
||||
about updates with:
|
||||
|
||||
```markdown
|
||||
il profilo aggiornato viene pushato qui e gli altri lo ricevono con
|
||||
`/plugin marketplace update gw-triage` (Claude Code) o `git pull`
|
||||
nella cartella clonata (Codex).
|
||||
```
|
||||
|
||||
In `## Problemi comuni`, replace the "Allegato saltato" entry and add
|
||||
one Codex entry:
|
||||
|
||||
```markdown
|
||||
- **"MCP Atlassian non disponibile"** → passi 1–2 dell'installazione
|
||||
Claude Code.
|
||||
- **"Allegato saltato"** → esegui il setup (token mancante, scaduto o
|
||||
revocato).
|
||||
- **Su Codex le skill non compaiono** → riesegui `./install-codex.sh`
|
||||
dalla cartella clonata e controlla i link in `~/.agents/skills/`.
|
||||
- **La issue finisce nell'epic sbagliata** → correggi in Jira e apri
|
||||
una issue su questo repo per aggiustare `config/routing.json` o il
|
||||
profilo in `knowledge/`.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Bump the plugin version**
|
||||
|
||||
In `.claude-plugin/plugin.json`, change `"version": "0.2.0"` to `"version": "0.3.0"`.
|
||||
|
||||
- [ ] **Step 5: Verify and commit**
|
||||
|
||||
```bash
|
||||
grep -n 'Codex' README.md | head -20
|
||||
python3 -c "import json; print(json.load(open('.claude-plugin/plugin.json'))['version'])"
|
||||
git add README.md .claude-plugin/plugin.json
|
||||
git commit -m "docs: Codex CLI install/usage instructions; bump to 0.3.0"
|
||||
```
|
||||
|
||||
Expected: Codex sections present; version prints `0.3.0`.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Live verification (needs the user's Jira credentials)
|
||||
|
||||
**Files:** none (verification only).
|
||||
|
||||
This task exercises the REST path for real. It creates one throwaway
|
||||
issue in the OA project — get the user's OK before running, and delete
|
||||
the issue afterwards.
|
||||
|
||||
- [ ] **Step 1: Netrc present**
|
||||
|
||||
If `~/.config/gw-triage/netrc` doesn't exist, run the setup skill flow
|
||||
first (or migrate from `~/.claude/settings.json` per setup Step 0.2).
|
||||
|
||||
- [ ] **Step 2: Auth check**
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}" --netrc-file ~/.config/gw-triage/netrc https://growingway.atlassian.net/rest/api/2/myself
|
||||
```
|
||||
|
||||
Expected: `200`.
|
||||
|
||||
- [ ] **Step 3: JQL search**
|
||||
|
||||
```bash
|
||||
curl -s --netrc-file ~/.config/gw-triage/netrc -G \
|
||||
--data-urlencode 'jql=project = OA ORDER BY created DESC' \
|
||||
--data-urlencode 'maxResults=3' \
|
||||
--data-urlencode 'fields=summary,status' \
|
||||
"https://growingway.atlassian.net/rest/api/3/search/jql" | head -c 400
|
||||
```
|
||||
|
||||
Expected: JSON with `issues` array.
|
||||
|
||||
- [ ] **Step 4: Create + comment + attach + delete a throwaway issue**
|
||||
|
||||
Create (body via temp file, per the skill):
|
||||
|
||||
```bash
|
||||
printf '%s' '{"fields":{"project":{"key":"OA"},"issuetype":{"name":"Task"},"summary":"[test gw-triage] verifica REST — da cancellare","description":"Test automatico del percorso REST di gw-triage. Cancellare."}}' > /tmp/gw-test-create.json
|
||||
curl -s --netrc-file ~/.config/gw-triage/netrc -H "Content-Type: application/json" -X POST -d @/tmp/gw-test-create.json "https://growingway.atlassian.net/rest/api/2/issue"
|
||||
```
|
||||
|
||||
Expected: JSON with a `key` (e.g. `OA-123`). With that KEY:
|
||||
|
||||
```bash
|
||||
printf '%s' '{"body":"commento di test"}' > /tmp/gw-test-comment.json
|
||||
curl -s -o /dev/null -w "%{http_code}" --netrc-file ~/.config/gw-triage/netrc -H "Content-Type: application/json" -X POST -d @/tmp/gw-test-comment.json "https://growingway.atlassian.net/rest/api/2/issue/<KEY>/comment"
|
||||
```
|
||||
|
||||
Expected: `201`. Attachment (any small local image or text file):
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}" -X POST -H "X-Atlassian-Token: no-check" --netrc-file ~/.config/gw-triage/netrc -F "file=@<some-file>" "https://growingway.atlassian.net/rest/api/3/issue/<KEY>/attachments"
|
||||
```
|
||||
|
||||
Expected: `200`. Then delete:
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}" --netrc-file ~/.config/gw-triage/netrc -X DELETE "https://growingway.atlassian.net/rest/api/2/issue/<KEY>"
|
||||
```
|
||||
|
||||
Expected: `204`. Clean up `/tmp/gw-test-*.json`.
|
||||
|
||||
- [ ] **Step 5: Codex smoke test (user-run)**
|
||||
|
||||
Ask the user to run, in a Codex session: `$setup` (should report the
|
||||
existing token works) and `$triage` with a sample message, stopping at
|
||||
the draft confirmation with "correggi: annulla". Confirm the skills
|
||||
were discovered and REST preflight passed.
|
||||
|
||||
- [ ] **Step 6: Claude Code regression (user-run)**
|
||||
|
||||
`/gw-triage:triage` with a sample report in a Claude Code session:
|
||||
MCP mode preflight, netrc detected for attachments. Cancel at the
|
||||
draft. Then push everything:
|
||||
|
||||
```bash
|
||||
git push
|
||||
```
|
||||
20
install-codex.sh
Executable file
20
install-codex.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Install the gw-triage skills for OpenAI Codex CLI by symlinking them
|
||||
# into ~/.agents/skills. Safe to re-run; updates arrive via `git pull`
|
||||
# in this clone (symlinks keep pointing at the updated files).
|
||||
set -eu
|
||||
|
||||
repo_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)
|
||||
dest="${HOME}/.agents/skills"
|
||||
|
||||
mkdir -p "$dest"
|
||||
for skill in triage setup map-repo; do
|
||||
if [ -e "$dest/$skill" ] && [ ! -L "$dest/$skill" ]; then
|
||||
echo "errore: $dest/$skill esiste già e non è un link simbolico — rimuovilo e rilancia" >&2
|
||||
exit 1
|
||||
fi
|
||||
ln -sfn "$repo_dir/skills/$skill" "$dest/$skill"
|
||||
echo "linked $dest/$skill -> $repo_dir/skills/$skill"
|
||||
done
|
||||
|
||||
echo "Fatto. Per aggiornare in futuro: git -C \"$repo_dir\" pull"
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: map-repo
|
||||
description: Use when generating or refreshing a codebase's triage profile for the gw-triage plugin — run from inside the repo to map. Triggers on /map-repo, "mappa questo repo", "aggiorna il profilo di triage".
|
||||
description: Use when generating or refreshing a codebase's triage profile for the gw-triage plugin — run from inside the repo to map. Triggers on /gw-triage:map-repo, $map-repo, "mappa questo repo", "aggiorna il profilo di triage".
|
||||
---
|
||||
|
||||
# Map-repo — profilo di triage del codebase
|
||||
@@ -12,6 +12,13 @@ and guide them to publish it to the gw-triage plugin repo.
|
||||
profile is written in English (it is read by the triage model, not by
|
||||
humans).
|
||||
|
||||
## 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. Paths below marked `<root>` are
|
||||
relative to it.
|
||||
|
||||
## Step 1 — Identify the repo
|
||||
|
||||
- `git rev-parse --show-toplevel` — if not a git repo, ask (Italian)
|
||||
@@ -20,8 +27,11 @@ humans).
|
||||
|
||||
## Step 2 — Survey
|
||||
|
||||
Read `${CLAUDE_PLUGIN_ROOT}/knowledge/README.md` (the profile format).
|
||||
Dispatch ONE exploration subagent with this prompt, filling <repo-path>:
|
||||
Read `<root>/knowledge/README.md` (the profile format).
|
||||
If the platform supports dispatching subagents, dispatch ONE
|
||||
exploration subagent with the prompt below, filling <repo-path>;
|
||||
otherwise perform the same survey yourself, covering all six points
|
||||
before writing anything:
|
||||
|
||||
> Survey the codebase at <repo-path> to build a triage profile.
|
||||
> Report back, with file evidence: (1) what the system does — main
|
||||
@@ -48,7 +58,7 @@ Write it to a temporary location first (the session scratchpad or
|
||||
Ask (Italian) for the local path of the user's gw-triage checkout;
|
||||
offer to `git clone <plugin-repo-url>` if they don't have one (read
|
||||
the URL from `git remote get-url origin` run in
|
||||
`${CLAUDE_PLUGIN_ROOT}` if available, otherwise ask).
|
||||
`<root>` if available, otherwise ask).
|
||||
|
||||
With the user's confirmation, in the checkout:
|
||||
1. Copy the profile to `knowledge/<repo-name>.md` (overwrite if
|
||||
@@ -59,4 +69,5 @@ With the user's confirmation, in the checkout:
|
||||
then `git commit -m "knowledge: add/update <repo-name> profile"`
|
||||
— ask before committing, and ask again before `git push`.
|
||||
4. Tell the user (Italian) that teammates receive the update with
|
||||
`/plugin marketplace update gw-triage`.
|
||||
`/plugin marketplace update gw-triage` on Claude Code, or with
|
||||
`git pull` in their gw-triage clone on Codex.
|
||||
|
||||
@@ -1,60 +1,83 @@
|
||||
---
|
||||
name: setup
|
||||
description: Use when configuring the Jira API credentials for gw-triage — first-time setup, an "allegato saltato" warning from triage, missing or expired JIRA_EMAIL/JIRA_API_TOKEN, or replacing a revoked token. Triggers on /gw-triage:setup, "configura il token", "gli allegati non funzionano".
|
||||
description: Use when configuring the Jira API credentials for gw-triage — first-time setup, an "allegato saltato" warning from triage, missing or expired credentials, or replacing a revoked token. Triggers on /gw-triage:setup, $setup, "configura il token", "gli allegati non funzionano".
|
||||
---
|
||||
|
||||
# Setup — token API Jira guidato
|
||||
|
||||
You guide the user through creating a Jira API token and storing it so
|
||||
the `triage` skill can attach screenshots to issues.
|
||||
You guide the user through creating a Jira API token and storing it in
|
||||
the gw-triage netrc file. The `triage` skill reads that file for its
|
||||
REST calls: screenshot attachments on every platform, plus search /
|
||||
create / comment when running under Codex.
|
||||
|
||||
**All interaction with the user happens in Italian.** This file is
|
||||
English for precision; never quote it to the user.
|
||||
|
||||
The only consumer of the token is the `triage` skill (its curl
|
||||
attachment call), which runs inside Claude Code. Credentials therefore
|
||||
go in the `env` block of `~/.claude/settings.json` — Claude Code
|
||||
injects them into every session, regardless of the user's shell. Never
|
||||
touch shell profiles.
|
||||
## 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.
|
||||
- **Store**: `~/.config/gw-triage/netrc`, mode 600. curl reads it at
|
||||
call time on every platform, so changes take effect immediately — no
|
||||
session restart, no shell configuration.
|
||||
- **Host**: the `site` value in `<root>/config/routing.json` without
|
||||
the scheme (e.g. `growingway.atlassian.net`).
|
||||
|
||||
**Keep the token out of replies and displayed commands.** Refer to it
|
||||
as "il token" and never repeat its value. Never inline a literal token
|
||||
on a shell command line — it ends up in the transcript and the process
|
||||
list. Shell variables may be passed as unexpanded `$VAR` references;
|
||||
literal values (pasted or read from a file) go through the temp netrc
|
||||
file described in Step 0.3.
|
||||
list. Write credentials into the netrc file with the file-writing
|
||||
tool — or, for values that live only in session env vars, via shell
|
||||
redirection with unexpanded `$VAR` references — then let curl read
|
||||
them via `--netrc-file`.
|
||||
|
||||
The verification call used throughout:
|
||||
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
--netrc-file ~/.config/gw-triage/netrc \
|
||||
https://<host>/rest/api/2/myself
|
||||
|
||||
## Step 0 — Check existing configuration
|
||||
|
||||
1. Run `test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo session || echo unset`.
|
||||
2. Read `~/.claude/settings.json` (if it exists) and note whether
|
||||
`env.JIRA_EMAIL` / `env.JIRA_API_TOKEN` are present.
|
||||
3. If credentials exist in either place, verify them. The check call is
|
||||
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
<credentials> \
|
||||
https://growingway.atlassian.net/rest/api/3/myself
|
||||
|
||||
(host = the `site` in `${CLAUDE_PLUGIN_ROOT}/config/routing.json`,
|
||||
without the scheme). For `<credentials>`:
|
||||
- session env vars set → `-u "$JIRA_EMAIL:$JIRA_API_TOKEN"`, with the
|
||||
`$` references left unexpanded for the shell to fill in — never
|
||||
substitute the values yourself.
|
||||
- literal values (from settings.json or a paste) → use the Write
|
||||
tool to create a netrc file in the session scratchpad directory:
|
||||
|
||||
machine growingway.atlassian.net
|
||||
login <email>
|
||||
password <token>
|
||||
|
||||
`chmod 600` it and pass `--netrc-file <path>` instead of `-u`.
|
||||
Delete this file before the skill ends, whatever the outcome.
|
||||
|
||||
Result:
|
||||
1. If `~/.config/gw-triage/netrc` exists and is readable, run the
|
||||
verification call.
|
||||
- `200` → tell the user (Italian) the token already works and ask
|
||||
whether they want to replace it anyway. If not, stop.
|
||||
- anything else → tell them the stored token no longer works
|
||||
(probably expired or revoked) and continue.
|
||||
- `401`/`403` → tell them the stored token no longer works
|
||||
(probably expired or revoked) and continue to Step 1.
|
||||
- anything else (timeout, DNS) → network problem, not credentials:
|
||||
report it (Italian) and stop.
|
||||
2. Otherwise look for legacy credentials, in order:
|
||||
- session env: `test -n "$JIRA_EMAIL" && test -n "$JIRA_API_TOKEN" && echo session || echo unset`
|
||||
- `~/.claude/settings.json` (if it exists): `env.JIRA_EMAIL` /
|
||||
`env.JIRA_API_TOKEN`.
|
||||
|
||||
If found in either place: write them to the netrc (Step 2 format,
|
||||
chmod 600) and run the verification call.
|
||||
|
||||
**Important — how to write the netrc depends on where the values
|
||||
came from:**
|
||||
- Values read from `~/.claude/settings.json` are literals you
|
||||
already hold: write the netrc with the file-writing tool as usual.
|
||||
- Session-env credentials must never be echoed or expanded by you:
|
||||
write the file via shell redirection with unexpanded references,
|
||||
e.g.
|
||||
|
||||
printf 'machine <host>\nlogin %s\npassword %s\n' \
|
||||
"$JIRA_EMAIL" "$JIRA_API_TOKEN" > ~/.config/gw-triage/netrc
|
||||
chmod 600 ~/.config/gw-triage/netrc
|
||||
|
||||
After writing, run the verification call.
|
||||
- `200` → tell the user (Italian) the existing credentials were
|
||||
migrated to the new store and work immediately; then do Step 3
|
||||
(clean up legacy stores) and Step 4. Done — skip token creation.
|
||||
- `401`/`403` → delete the netrc just written, tell them the old
|
||||
token no longer works, continue to Step 1.
|
||||
- anything else (timeout, DNS) → network problem, not credentials:
|
||||
report it (Italian) and stop, leaving the netrc in place — it may
|
||||
verify fine later.
|
||||
3. Nothing found → first-time setup, continue to Step 1.
|
||||
|
||||
## Step 1 — Token creation (user, in the browser)
|
||||
|
||||
@@ -67,52 +90,53 @@ Print in Italian, compactly:
|
||||
3. Incolla qui email aziendale e token (vanno bene anche su due righe).
|
||||
|
||||
Add one line: il token verrà salvato in chiaro in
|
||||
`~/.claude/settings.json` sul suo computer, quindi non condividere né il
|
||||
file né questa conversazione.
|
||||
`~/.config/gw-triage/netrc` sul suo computer, quindi non condividere né
|
||||
il file né questa conversazione.
|
||||
|
||||
End the turn and wait. If the reply contains only one of the two
|
||||
values, ask for the missing one. If the user can't create the token
|
||||
(no permission, page unreachable), stop and suggest asking whoever
|
||||
manages the Atlassian accounts.
|
||||
|
||||
## Step 2 — Verify before saving
|
||||
## Step 2 — Save, then verify
|
||||
|
||||
Run the Step 0.3 check with the pasted values — literals, so via the
|
||||
temp netrc file, never `-u` on the command line.
|
||||
1. Create `~/.config/gw-triage/` if missing. Write the netrc file with
|
||||
the file-writing tool:
|
||||
|
||||
- `200` → proceed to Step 3.
|
||||
- `401`/`403` → wrong email or token (a common cause: copied with a
|
||||
trailing space or truncated). Ask the user to re-copy and re-paste,
|
||||
then verify again; stop after the third failed verification overall
|
||||
and suggest creating a fresh token.
|
||||
- Anything else (timeout, DNS) → network problem, not credentials:
|
||||
report it and stop; the pasted token stays valid for a later retry.
|
||||
machine <host>
|
||||
login <email>
|
||||
password <token>
|
||||
|
||||
## Step 3 — Save to settings.json
|
||||
Then `chmod 600 ~/.config/gw-triage/netrc`.
|
||||
2. Run the verification call.
|
||||
- `200` → Step 3.
|
||||
- `401`/`403` → wrong email or token (a common cause: copied with a
|
||||
trailing space or truncated). Ask the user to re-copy and
|
||||
re-paste, rewrite the file, verify again; after the third failed
|
||||
verification overall, delete the netrc file, stop, and suggest
|
||||
creating a fresh token.
|
||||
- Anything else (timeout, DNS) → network problem, not credentials:
|
||||
report it and stop. Leave the netrc in place — it may verify fine
|
||||
later.
|
||||
|
||||
Update `~/.claude/settings.json` with Read + Edit/Write (never shell
|
||||
text-mangling):
|
||||
## Step 3 — Clean up legacy stores
|
||||
|
||||
- File missing → create it containing only
|
||||
`{"env": {"JIRA_EMAIL": "<email>", "JIRA_API_TOKEN": "<token>"}}`.
|
||||
- Valid JSON → add or overwrite the two keys inside the existing `env`
|
||||
object (create the object if absent). Preserve every other key
|
||||
untouched.
|
||||
- Invalid JSON → do NOT overwrite; show the user the parse error and
|
||||
stop.
|
||||
|
||||
Leftover check: old installs configured the shell profile instead. Run
|
||||
`fish -c 'set -U' 2>/dev/null | grep -i jira` and
|
||||
`grep -l JIRA_API_TOKEN ~/.config/fish/config.fish ~/.config/fish/conf.d/*.fish ~/.zshrc ~/.bashrc ~/.zprofile ~/.profile 2>/dev/null`.
|
||||
If anything turns up, tell the user (Italian) to remove it so it can't
|
||||
shadow the new token (fish: `set -e JIRA_EMAIL; set -e JIRA_API_TOKEN`;
|
||||
altrimenti togliere gli `export` dal file indicato).
|
||||
1. `~/.claude/settings.json`: if it exists and has `env.JIRA_EMAIL` /
|
||||
`env.JIRA_API_TOKEN`, offer (Italian) to remove those two keys —
|
||||
with the file tools (Read + Edit), never shell text-mangling, and
|
||||
preserving every other key. If the file is invalid JSON, don't
|
||||
touch it; just tell the user it should be cleaned up by hand.
|
||||
2. Shell profiles: run
|
||||
`fish -c 'set -U' 2>/dev/null | grep -i jira` and
|
||||
`grep -l JIRA_API_TOKEN ~/.config/fish/config.fish ~/.config/fish/conf.d/*.fish ~/.zshrc ~/.bashrc ~/.zprofile ~/.profile 2>/dev/null`.
|
||||
If anything turns up, tell the user (Italian) to remove it so it
|
||||
can't shadow the netrc (fish: `set -e JIRA_EMAIL; set -e
|
||||
JIRA_API_TOKEN`; altrimenti togliere gli `export` dal file
|
||||
indicato).
|
||||
|
||||
## Step 4 — Report
|
||||
|
||||
Delete the temp netrc file if one was created.
|
||||
|
||||
In Italian: token verificato e salvato. Vale dalle **prossime** sessioni
|
||||
di Claude Code — quelle già aperte vanno riavviate prima che l'allegato
|
||||
automatico funzioni. Per sostituirlo o dopo una revoca basta rilanciare
|
||||
`/gw-triage:setup`.
|
||||
In Italian: token verificato e salvato in `~/.config/gw-triage/netrc`.
|
||||
Vale da subito, anche nelle sessioni già aperte. Per sostituirlo o dopo
|
||||
una revoca basta rilanciare il setup: `/gw-triage:setup` su Claude
|
||||
Code, `$setup` su Codex.
|
||||
|
||||
@@ -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,65 @@ 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`. `<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
|
||||
|
||||
**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 \
|
||||
<site>/rest/api/2/myself
|
||||
|
||||
- `401`/`403` → STOP (Italian): token scaduto o revocato,
|
||||
rilancia `$setup`.
|
||||
- anything else → STOP (Italian): problema di rete verso Jira, non
|
||||
di credenziali — riprova più tardi.
|
||||
|
||||
## Step 1 — Input
|
||||
|
||||
@@ -44,8 +83,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 `<root>/config/routing.json` and every `.md` file in
|
||||
`<root>/knowledge/` except `README.md`.
|
||||
|
||||
## Step 3 — Classify
|
||||
|
||||
@@ -64,20 +103,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 = <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
|
||||
(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": "<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)
|
||||
|
||||
@@ -100,9 +165,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": "<area epic>"}}`.
|
||||
- MCP mode: call `createJiraIssue` with `cloudId`, `projectKey`,
|
||||
`issueTypeName` (`Bug` or `Task`), `summary`, `description`, the
|
||||
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
|
||||
summary and stop — nothing partial to clean up (the attachment step
|
||||
@@ -110,17 +199,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=@<screenshot-path>" \
|
||||
"<site>/rest/api/3/issue/<ISSUE-KEY>/attachments"
|
||||
|
||||
`<site>` 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user