Skip to main content
ClaudeWave
EN, English
Skill12k repo starsupdated 4d ago

phoenix-github

This Claude Code skill provides access to GitHub issue, label, and project board management for the Arize-ai/phoenix repository via the gh CLI. Use it when filing roadmap epics, triaging bugs, applying component or priority labels, managing the Phoenix roadmap project board, or querying issue and project state. The skill references a comprehensive label taxonomy covering components like UI, server, traces, evals, datasets, and others, plus priority and status labels for organizing work.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/Arize-ai/phoenix /tmp/phoenix-github && cp -r /tmp/phoenix-github/.agents/skills/phoenix-github ~/.claude/skills/phoenix-github
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Phoenix GitHub

Reference for managing issues, labels, project boards, and sprint operations on
`Arize-ai/phoenix` using the `gh` CLI.

## Repository and Boards

```
Arize-ai/phoenix
```

There are **two** project boards. Pick deliberately.

| Board | Number | Project ID | What it holds |
|---|---|---|---|
| **phoenix** (sprint board) | [#42](https://github.com/orgs/Arize-ai/projects/42) | `PVT_kwDOA5FfSM4AIM-T` | Everything. ~6.3k items, Sprint/Points/Priority fields. **This is the board sprint work runs on.** |
| **phoenix roadmap** | [#45](https://github.com/orgs/Arize-ai/projects/45) | `PVT_kwDOA5FfSM4AJaRo` | ~75 high-level epics with Start/Target dates. No sprints. |

Day-to-day sprint operations mean board **#42**. Roadmap epics with dates live
on **#45**.

## Quick Reference

| Task | See |
|---|---|
| Close out a sprint / roll slipped tickets | [Sprint Operations](#sprint-operations) |
| Check the board is up to date | [Board Hygiene](#board-hygiene) |
| Check nobody is starving or buried | [Ticket Load Health](#ticket-load-health) |
| Run a standup — recent work and work in flight per person | [Standup](#standup) |
| Keep roadmap epics current / flag ones needing planning | [Roadmap Health](#roadmap-health) |
| File a roadmap epic | [Roadmap Issues](#roadmap-issues) |
| Add an epic to the roadmap board (#45) | [Putting the Epic on the Roadmap Board](#putting-the-epic-on-the-roadmap-board) |
| Apply the right labels | [Label Taxonomy](#label-taxonomy) |
| Set project fields by hand | [Project Field Mechanics](#project-field-mechanics) |
| Create a bug or feature request | [Standard Issues](#standard-issues) |

---

## Tooling

Five bundled scripts under `scripts/` back the tech-lead workflows. They read
the roster, the sprint calendar, and all field IDs **live** — nothing about a
person, sprint, or ticket is hardcoded.

```bash
cd .agents/skills/phoenix-github/scripts

# Sprint board (#42) — needs a snapshot first
./snapshot.sh board.json     # ~60-90s, walks the whole board once
./health.py   board.json     # hygiene + load report (read-only)
./rollover.py board.json     # sprint rollover plan (dry run by default)
./standup.py  board.json     # per-person did/doing report (read-only;
                             # snapshot optional but recommended)

# Roadmap board (#45) — small, fetches live
./roadmap.py                 # roadmap audit (dry run by default)
```

**For board #42, snapshot once and run every check off that file.** The
ProjectV2 API has no server-side field filter, so a full read is ~63 sequential
pages. Re-taking the snapshot per check wastes minutes.

A snapshot is a **read cache, not a source of truth for writes.** Anything
closed or moved since it was taken still reads as open in the file, so
`rollover.py --apply` refuses to run against a snapshot older than 2 hours
(`PHOENIX_SNAPSHOT_MAX_AGE_MIN`; override with `--stale-ok` if you know the file
is still accurate). Re-snapshot before applying, and again afterwards.

Board #45 is ~75 items — one page — so `roadmap.py` just fetches it each run.

Every script that writes is **dry-run by default** and takes `--apply`.

Tunable via env vars: `PHOENIX_MIN_TICKETS` (3), `PHOENIX_MAX_TICKETS` (15),
`PHOENIX_ROSTER_TEAM` (`oss-eng`; comma-separated list of org teams),
`PHOENIX_ROSTER_EXCLUDE` (empty; comma-separated logins to omit from all
reporting), `PHOENIX_ROSTER_INCLUDE` (empty; comma-separated logins to add to
the roster regardless of team membership), `PHOENIX_STANDUP_DAYS` (2),
`PHOENIX_PROJECT_NUMBER` (42), `PHOENIX_SNAPSHOT_MAX_AGE_MIN` (120),
`PHOENIX_ISSUE_LIMIT` (5000). Team-wide values live in `.claude/settings.json`
(`env` block); personal overrides go in `.claude/settings.local.json`. Neither
is read by a plain shell — `export` them when running the scripts outside
Claude Code.

---

## Sprint Operations

Sprints are 14 days, defined by the **Sprint** iteration field on board #42
(field ID `PVTIF_lADOA5FfSM4AIM-TzgFYwU4` — stable). Individual **iteration IDs
rotate every sprint, so always resolve them live**; never hardcode one.

```bash
# Current and upcoming sprints
gh api graphql -F org=Arize-ai -F num=42 -f query='
query($org: String!, $num: Int!) {
  organization(login: $org) { projectV2(number: $num) {
    field(name: "Sprint") { ... on ProjectV2IterationField {
      id configuration { iterations { id title startDate duration } } } } } } }'
```

The current sprint is the iteration whose `[startDate, startDate + duration)`
window contains today.

> **New iterations cannot be created through the API.** If no future sprint
> exists, add it on the Sprint field in the GitHub UI before rolling anything
> over. The scripts fail with a clear message rather than guessing.

### Sprint Close-Out

Run at the end of each sprint. Any ticket still open and not Done rolls to the
next sprint and gets a comment recording the slip.

```bash
./snapshot.sh board.json
./rollover.py board.json                 # 1. review the plan (changes nothing)
./rollover.py board.json --apply         # 2. move them + comment
```

Slip comment posted on each rolled ticket:

```markdown
Slipped from **Sprint 11-21-33** → moved to **Sprint 11-21-34**.

Rolled over during sprint close-out.
```

Useful flags:

| Flag | Effect |
|---|---|
| *(none)* | Dry run — prints the plan, changes nothing |
| `--apply` | Perform the moves and post comments |
| `--stranded` | Also sweep tickets left behind on already-completed sprints |
| `--only 123,456` | Restrict to specific issue numbers |
| `--no-comment` | Move without commenting (use for bulk cleanup of old strays) |
| `--stale-ok` | Apply from a snapshot older than the freshness limit |

**"Stranded" means a sprint that has actually finished**, taken from the board's
own completed-iteration list. Work parked on a *future* iteration is deliberate
planning and is never pulled backwards, no matter how many iterations exist.

**Always review the dry run before `--apply`.** Rolling a sprint com