# Channels - Board adapter (GitHub Projects v2 status move)

**Precondition gate:** `figmaConfig.board.enabled === true` AND `figmaConfig.board.provider === "github-projects-v2"` AND `figmaConfig.github.projectV2Id` non-empty. If not met, the channel is greyed in the menu (Step 3b rule) and the adapter is skipped silently in flag-mode dispatch.

**Default target column:** `inReview`  -  read from `figmaConfig.github.fieldOptions.status.inReview` (the option ID, e.g. `bdb0d8ef`). Other column targets (e.g. `done`, `bugfix`) overridable via flag `--board-status <key>` where `<key>` matches a key under `fieldOptions.status`.

**Token:** `prefs.global.keychainMapping.github_projects` (preferred  -  must include `project,read:project` scopes). Fallback chain: `keychainMapping.github` → standard key `${USER}_Github_Access_Token`. Resolve via `~/.claude/lib/credential-store.sh get <key>` (reads the macOS Keychain). Token must NOT be passed on the CLI  -  export as `GH_TOKEN` env var only (per memory rule on token leakage).

**Item lookup:** the issue's project item ID is fetched via GraphQL `repository.issue(number).projectItems(first:5)` filtered to `project.id === figmaConfig.github.projectV2Id`. If the issue is not yet in the project, dispatch silently no-ops with reason `"issue not on board"` in the summary.

**Mutation:** GraphQL `updateProjectV2ItemFieldValue(input: { projectId, itemId, fieldId: figmaConfig.github.projectV2Fields.status, value: { singleSelectOptionId: <target> } })`. Verify by re-querying `fieldValueByName(name: "Status")` on the same item; assert `name === target column label` from `figmaConfig.board.columns`.

**Multi-repo:** runs **once** (board status is keyed off the GitHub Issue, not per-PR). When `state.projects[].length > 1`, the primary repo's issue is the target; extras' PRs do not trigger additional moves.

**Idempotency:** if the issue is already on the target column, the mutation is a no-op and the adapter reports `"already in <column>"` in the summary.

**Additional behaviors handled inline by this adapter** (no separate contract file): token scope upgrade flow (`gh auth refresh -s project,read:project`), field-ID auto-discovery for repos missing `projectV2Fields.status` in figma-config, error-recovery (token expired vs scope insufficient).
