docs: implementation plan for Codex support; fix search endpoint to v3 search/jql
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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=<urlencoded>` |
|
||||
| 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` |
|
||||
|
||||
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
|
||||
```
|
||||
Reference in New Issue
Block a user