# Grok account parity — finish integration (composer-2.5)

> **For agentic workers:** REQUIRED SUB-SKILL: Use /ship or runplan. Steps use checkbox syntax.

**Goal:** Finish Grok tray parity so add-account UI, menu labels, tests, and gates work end-to-end without risking the protected `roy-grok` token.

**Architecture:** Foundation already on `main` (`771a9c6`): registry/kind GROK, `grok_oauth`/`grok_health`/`grok_auth_operation`, tray wiring, bootstrap copy import. Remaining work is lifecycle event-kind alignment with Indicator, secondary-only usage labels, and tests — **never call auth.x.ai token endpoint against roy-grok**.

**Tech Stack:** Python 3.13, pytest, ruff, mypy.

**Spec:** `docs/specs/2026-07-10-grok-account-parity-design.md`

---

## Wave Plan

| Wave | Tasks | Files | Parallel? |
|------|-------|-------|-----------|
| 1 | Task 1 | `grok_auth_operation.py`, `tests/test_grok_accounts.py` | single |
| 2 | Task 2 | `indicator.py`, `tray_model.py`, `account_card.py` if needed | single |
| 3 | Task 3 | tests + gate0 | single |

## Task 1: Grok lifecycle events match Indicator

**Wave:** 1  
**Blocks:** 2, 3  
**Blocked by:** —

**Files:**
- Modify: `grok_auth_operation.py`
- Modify: `tests/test_grok_accounts.py`

**Contract:**
- `add` / `reauthenticate` yield event kinds Indicator already handles: `started`, `prompt_ready` (not bare `prompt`), `success`, `failure`, `collision`.
- `prompt_ready.prompt` has `.url` and `.raw_text` (device verification URI + user code).
- Poll for device tokens happens **after** `prompt_ready` yield so UI can show the code.
- `roy-grok` re-auth/remove still require `SYSTRAY_ALLOW_ROY_GROK_MUTATION=1`.
- Import path remains **copy-only** (no token endpoint). Mock network in tests.

**Acceptance:**
- `TMPDIR=... python3 -m pytest tests/test_grok_accounts.py -q` → PASS

## Task 2: Indicator / menu polish for Grok device prompt

**Wave:** 2  
**Blocked by:** 1  

**Files:**
- Modify: `indicator.py` if Grok needs notify-only path when `session is None` on `prompt_ready`
- Verify: `_providers` includes GROK; add-account flow does not crash on session=None

**Contract:**
- `prompt_ready` with `session is None` shows notification (or dialog) with URL/code; does not call `terminate_process` / `submit_code`.
- Existing Codex/Claude flows unchanged.

**Acceptance:**
- `python3 -c "from indicator import Indicator; from grok_auth_operation import GrokAuthOperation; print('ok')"`
- `TMPDIR=... python3 -m pytest tests/test_provider_services.py tests/test_grok_accounts.py -q` → PASS

## Task 3: Gate0 clean

**Wave:** 3  
**Blocked by:** 2  

**Files:** any ruff/mypy fixes in touched modules only

**Acceptance:**
- `python3 -m pytest tests/test_grok_accounts.py -q && ruff check grok_*.py tests/test_grok_accounts.py indicator.py tray_model.py account_card.py account_registry.py && mypy grok_oauth.py grok_health_client.py grok_auth_operation.py` → exit 0

**HARD safety (every task):**
- NEVER POST to `https://auth.x.ai/oauth2/token` against the live `roy-grok` / `~/.grok` credentials in tests or scripts.
- Device-code tests must mock `start_device_code` / `poll_device_code`.
