---
name: ic-leaderboard
description: Connect a user's GitHub account to the Immersive Commons commits leaderboard, opt them in, and verify their rank. Use when the human says "put me on the leaderboard", "get me on /floor10/commits", "connect my GitHub to IC", "show me my leaderboard rank", or "opt me out of the commits board". Requires an IC agent token with scopes `github:link` + `leaderboard:manage` (granted at ft-member tier and above).
---

You help an agent's human join the IC commits leaderboard at https://www.immersivecommons.com/floor10/commits. The leaderboard counts weekly commits across the linked GitHub account and renders on the FT10 kiosk TV. Three steps: confirm the user can grant the scopes, link their GitHub, opt them in.

## Pre-flight (always)

1. **Token check.** Need `FLOOR10_AGENT_TOKEN` (or equivalent) with scopes `github:link` AND `leaderboard:manage`. If missing either, the user's tier is below ft-member or they minted a narrower token. Either way: stop and tell them.

   Smoke probe:
   ```bash
   curl -H "Authorization: Bearer $FLOOR10_AGENT_TOKEN" \
     https://www.immersivecommons.com/api/leaderboard/me
   ```
   A 401 means no token. A 403 means wrong scope. A 200 with `optIn: false` is the starting state for the rest of this flow.

2. **GitHub PAT.** You'll need a GitHub Personal Access Token from the user. Tell them:
   > Make a PAT at https://github.com/settings/tokens — fine-grained is fine, no scopes required (the `/user` endpoint is open to any valid PAT). Paste it back here. The IC server discards it after verification; only your GitHub username gets stored.

   They paste. You read once into a runtime variable; **do not log it, do not echo it back, do not write it to a file**.

## The pipeline (always this order)

### 1. Connect GitHub

```bash
curl -X POST https://www.immersivecommons.com/api/leaderboard/connect-github \
  -H "Authorization: Bearer $FLOOR10_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"pat\": \"$GITHUB_PAT\"}"
```

Possible responses:

- **`200 { ok: true, github: { login, id, name?, avatarUrl? } }`** — linked. Tell the user "linked GitHub as `<login>`."
- **`422`** — GitHub rejected the PAT. Ask the user to mint a fresh one (their existing PAT may be expired or wrong-scoped). Don't auto-retry.
- **`400`** — PAT was missing/empty/oversized. Validation issue on our side.
- **`403`** — your token doesn't have `github:link`, OR your tier was demoted. Stop.
- **`502`** — GitHub had a transient. Retry once after 10s; if it fails again, abort and tell the user.
- **`500`** — Clerk write failed. Tell the user; offer to retry.

If your client speaks MCP, use the tool form instead:
```jsonc
{
  "name": "ic_leaderboard_connect_github",
  "arguments": { "pat": "<value>" }
}
```

**After this call returns**, drop the PAT variable. Don't keep it in memory.

### 2. Opt in

```bash
curl -X POST https://www.immersivecommons.com/api/leaderboard/optin \
  -H "Authorization: Bearer $FLOOR10_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"optIn": true}'
```

Possible responses:

- **`200 { ok: true, optIn: true, github_username }`** — you're on. Next rendered snapshot (weekly cron) will include them.
- **`409 { error_kind: "no_github_link" }`** — opt-in refused because there's no linked GitHub. Step 1 didn't complete OR was never run. Tell the user; go back to step 1.
- **`403`** — wrong scope or demoted. Stop.

MCP form:
```jsonc
{
  "name": "ic_leaderboard_set_optin",
  "arguments": { "optIn": true }
}
```

### 3. Verify status

```bash
curl -H "Authorization: Bearer $FLOOR10_AGENT_TOKEN" \
  https://www.immersivecommons.com/api/leaderboard/me
```

Response shape:
```json
{
  "ok": true,
  "optIn": true,
  "github_username": "vmihalis",
  "github_link_source": "agent_pat",
  "github_verified_at": "2026-05-12T18:30:00.000Z",
  "this_week": {
    "count": 47,
    "rank": 3,
    "total": 12,
    "generated_at": "2026-05-12T09:00:00.000Z"
  }
}
```

If `this_week` is missing, the user is opted in but the refresh cron hasn't run since they joined. Tell them: "you're on; your rank populates at the next refresh (~20 min)." Don't poll tightly — the cron fires about every 20 minutes (running totals for the current Mon–Sun PT week).

MCP form:
```jsonc
{
  "name": "ic_leaderboard_get_status",
  "arguments": {}
}
```

## What you DON'T do

- **Don't store the PAT.** Read it once, send it once, drop the variable.
- **Don't log the PAT** in any form (no `console.log(pat)`, no `console.log(body)` if `body` includes it, no error message that echoes it).
- **Don't echo the PAT** back to the user — they already have it.
- **Don't ask for the PAT before tier-checking.** If the user is below ft-member, getting their PAT first is wasted trust. Smoke-probe `/api/leaderboard/me` first; only ask if you get past the 403 gate.
- **Don't auto-opt-out without asking.** "Hide me from the leaderboard" should be an explicit user request.
- **Don't retry a 422 (PAT rejected) silently.** Bad PATs reflect on the user's GitHub account state, not a transient — they need to fix it on GitHub's side.

## Edge cases

**"I already linked via the Clerk OAuth browser flow."** No problem. `connect-github` is idempotent — re-running it overwrites the publicMetadata field. The OAuth link stays put. `/api/leaderboard/me` shows `github_link_source: "agent_pat"` after a successful PAT flow.

**"I'm an ic-member but my tier just got demoted to public."** The Layer-3 live-tier check will refuse both `connect-github` and `set_optin` with 403. Tell the user; point them at `/membership` to re-request ft-member (or higher).

**"My PAT works for me but the cron says 'GITHUB_LEADERBOARD_PAT not configured'."** That's a server-side ops problem (Ray hasn't set the env var yet). The link is recorded, but the weekly cron can't fetch your commits. Surface this to the user with the caveat that their rank won't populate until Ray fixes the env.

**"My GitHub username changed on GitHub.com."** The link stores the old username. Re-run `connect-github` with a fresh PAT for the renamed account — `publicMetadata.github_username` overwrites.

**"Can I be on the leaderboard with multiple GitHub accounts?"** No. The PAT path stores ONE username. If you want to track commits across multiple accounts, link your "main" one and ask Ray about adding a multi-account model (Phase 5+).

## Useful reference

- **Endpoint base**: `https://www.immersivecommons.com`
- **Leaderboard page (human-visible)**: `/floor10/commits`
- **Cron cadence**: every ~20 min (running totals for the current Mon–Sun PT week)
- **Required scopes**: `github:link` (write), `leaderboard:manage` (write + read)
- **Tier minimum**: `ft-member`
- **Sister skills**: `floor10-submit` (highlights), `ic-onboarding` (sign-up via device-code), `ic-events` (Phase 4)
