# 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 ```