diff --git a/docs/codex-support-design.md b/docs/codex-support-design.md new file mode 100644 index 0000000..8c7dc3d --- /dev/null +++ b/docs/codex-support-design.md @@ -0,0 +1,172 @@ +# gw-triage — Codex CLI support + +Date: 2026-07-10 +Status: approved + +## Problem + +The plugin only runs under Claude Code: distribution relies on the +Claude plugin marketplace, skills locate their data via +`${CLAUDE_PLUGIN_ROOT}`, Jira access goes through the Atlassian MCP +plugin, and credentials live in the `env` block of +`~/.claude/settings.json`. Teammates on OpenAI Codex CLI can't use any +of it. Goal: full parity — `triage`, `setup`, and `map-repo` all work +on Codex, from the same repo, with no duplicated skill files. + +## Decisions (agreed 2026-07-10) + +1. **Scope**: full parity for all three skills. +2. **Jira transport on Codex**: plain REST via curl with the Jira API + token. No MCP configuration on Codex. Claude Code keeps its MCP + path unchanged. +3. **Skill files**: one SKILL.md per skill, shared by both platforms, + branching internally where behavior differs. +4. **Credentials**: a single netrc file at `~/.config/gw-triage/netrc` + used by curl on both platforms, replacing the settings.json env + block as the primary store. + +## Verified platform facts + +- Codex discovers skills in `.agents/skills` (project, walking up to + repo root) and `~/.agents/skills` (user level). Symlinked skill + directories are followed. +- Skills use the same SKILL.md format (frontmatter `name` + + `description`); invoked explicitly as `$` or implicitly via + the description. +- Codex's `[shell_environment_policy]` env injection filters names + containing `TOKEN` by default and has open reliability issues — + ruled out in favor of the netrc file. +- Jira Cloud REST API v2 (`/rest/api/2/…`) is still served and accepts + plain-text descriptions, avoiding the ADF JSON required by v3 + `createIssue`. v2 is legacy; if Atlassian retires it, the REST-mode + steps move to v3 + minimal ADF paragraphs. + +## Design + +### 1. Distribution + +Repo structure unchanged. Codex users clone the repo anywhere and +symlink each skill directory into `~/.agents/skills/`: + + ~/.agents/skills/triage -> /skills/triage + ~/.agents/skills/setup -> /skills/setup + ~/.agents/skills/map-repo -> /skills/map-repo + +A small `install-codex.sh` at the repo root creates/refreshes the +symlinks idempotently. Updates arrive with `git pull` in the clone. + +Skill names stay as-is so Claude Code commands don't change +(`/gw-triage:triage`). On Codex they are `$triage`, `$setup`, +`$map-repo`; the generic names could collide with other installed +skills — accepted risk for a three-person team, noted in the README. + +### 2. Platform detection and root resolution + +Each SKILL.md gets a short "Environment" preamble: + +- **Root**: `${CLAUDE_PLUGIN_ROOT}` if set; otherwise resolve the real + path (symlinks followed) of the skill's own directory and go up two + levels. `config/` and `knowledge/` are addressed relative to that + root everywhere. +- **Mode** (triage only): Atlassian MCP tools available → MCP mode + (today's behavior, unchanged); otherwise → REST mode. + +### 3. Credentials — netrc file + +`setup` writes `~/.config/gw-triage/netrc`: + + machine growingway.atlassian.net + login + password + +(machine host derived from `site` in routing.json), `chmod 600`. Every +curl call on both platforms passes `--netrc-file +~/.config/gw-triage/netrc`, read at call time — no session restart +needed after setup, and no secrets on command lines or in process +listings. + +`setup` itself becomes platform-neutral (file operations + curl only): + +- Verify pasted credentials against `GET /rest/api/2/myself` before + saving (3-attempt limit, network-vs-auth error distinction — as + today). +- **Migration**: if credentials already exist in the session env or in + `~/.claude/settings.json` `env`, verify them and offer to migrate + them into the netrc; suggest removing the settings.json entries + (leftover shell-profile check stays). +- The temp-netrc-for-literals dance disappears: the real netrc file IS + the store, written before verification and deleted only if + verification ultimately fails. + +`triage` reads the netrc as the primary credential source and falls +back to `JIRA_EMAIL`/`JIRA_API_TOKEN` env vars (legacy installs) for +the attachment step. + +### 4. Triage in REST mode + +Used on Codex. (Claude Code without MCP still stops and points at the +Atlassian plugin install, as today — MCP remains the intended path +there.) + +On Codex the token is **required** — it is the only transport. Missing +or invalid netrc → stop with `$setup` instructions. + +| Step | MCP mode (unchanged) | REST mode | +|---|---|---| +| Preflight | `getAccessibleAtlassianResources` | `GET /rest/api/2/myself` → expect 200 | +| Duplicate search | `searchJiraIssuesUsingJql` | `GET /rest/api/2/search?jql=` | +| Create | `createJiraIssue` | `POST /rest/api/2/issue` (JSON body: project, issuetype, summary, plain-text description, assignee accountId, parent epic) | +| Comment on duplicate | `addCommentToJiraIssue` | `POST /rest/api/2/issue/{key}/comment` | +| Attach screenshot | curl (as today) | same curl, `--netrc-file` | + +`cloudId` in routing.json becomes MCP-only; REST mode uses `site`. +Classification, drafting, confirmation flow, and Italian interaction +are identical in both modes. + +### 5. map-repo + +Two touch-ups: + +- Root resolution per §2 (replaces `${CLAUDE_PLUGIN_ROOT}`). +- Survey step: "dispatch one exploration subagent **if the platform + supports subagent dispatch; otherwise perform the survey yourself**, + covering the same six points." +- Publish step: note that Codex teammates receive updates with + `git pull` in their clone (Claude Code users keep + `/plugin marketplace update gw-triage`). + +### 6. README + +- New "Installazione (Codex)" section: clone, `./install-codex.sh`, + run `$setup`, daily use via `$triage`. +- Token section updated: netrc path, token optional on Claude Code + (attachments only), **required** on Codex. +- Per-platform update instructions and troubleshooting entries. + +## Error handling + +- REST calls: treat non-2xx as failure; show the raw body with a + one-line Italian summary. Create-issue failure stops before the + attachment step (nothing partial), as today. +- Netrc unreadable/missing on Codex → stop with setup guidance; on + Claude Code → warn once that attachment will be skipped, proceed. +- JQL must be URL-encoded in REST mode (curl `--data-urlencode` with + `-G`). + +## Testing + +- REST commands exercised directly against Jira: `myself`, JQL search, + create on a throwaway issue, comment, attachment — then delete the + throwaway. +- Codex smoke test: skills discovered after `install-codex.sh`, + `$triage` dry run reaches the draft step, `$setup` full run. +- Claude Code regression: `/gw-triage:triage` full run with netrc in + place (MCP mode + netrc attachment), `/gw-triage:setup` migration + path from settings.json env vars. + +## Out of scope + +- Renaming skills or namespacing for Codex. +- Moving Claude Code off MCP. +- Windows support (team is on macOS). +- v3/ADF migration (documented as future work if v2 is retired).