diff --git a/docs/codex-support-design.md b/docs/codex-support-design.md index 8c7dc3d..2e89544 100644 --- a/docs/codex-support-design.md +++ b/docs/codex-support-design.md @@ -114,7 +114,7 @@ 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/2/search?jql=` | +| Duplicate search | `searchJiraIssuesUsingJql` | `GET /rest/api/3/search/jql?jql=` (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` | diff --git a/docs/codex-support-plan.md b/docs/codex-support-plan.md new file mode 100644 index 0000000..3cc952c --- /dev/null +++ b/docs/codex-support-plan.md @@ -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//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 `/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 ` / `login ` / `password `, 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 `/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:///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 + (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 + login + password + + 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`. `` 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. 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 + +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 `/config/routing.json` and every `.md` file in +`/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 = AND text ~ "" 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=' \ + --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, 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) + +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": ""}}`. +- 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 +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=@" \ + "/rest/api/3/issue//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 `/browse/`, 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 `` are +relative to it. +``` + +Then replace `${CLAUDE_PLUGIN_ROOT}/knowledge/README.md` with `/knowledge/README.md` (Step 2) and `${CLAUDE_PLUGIN_ROOT}` with `` in Step 4's remote-URL instruction. + +- [ ] **Step 3: Make the survey subagent optional** + +Replace: + +``` +Dispatch ONE exploration subagent with this prompt, filling : +``` + +with: + +``` +If the platform supports dispatching subagents, dispatch ONE +exploration subagent with the prompt below, filling ; +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 '' 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); `` 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 . +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//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=@" "https://growingway.atlassian.net/rest/api/3/issue//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/" +``` + +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 +```