| 1 | # feat(x): demote Grok CLI to opt-in backup |
| 2 | |
| 3 | Stop using the Grok CLI as the default X backend. A leftover `~/.grok/auth.json` must never steal the X lane. Grok stays as a pin-only backup: off unless LAST30DAYS_X_BACKEND=grok or --x-backend grok. |
| 4 | |
| 5 | ### Requirements |
| 6 | - R1. Unpinned auto chain is bird → xai → xurl → xquik. Bird is first. Grok is not a member. Presence of ~/.grok/auth.json (ok, expired, or error) must not change which backend an unpinned run uses. |
| 7 | - R2. Grok remains a valid explicit selection: LAST30DAYS_X_BACKEND=grok and --x-backend grok. A pin forces grok with no failover. If grok is unusable, X is unconfigured and doctor/footer say so with the existing login hint. |
| 8 | - R3. Doctor "will use: grok" only when grok is pinned and the probe is OK or DEGRADED. Unpinned, grok may appear as unused opt-in ("available, unused — pin LAST30DAYS_X_BACKEND=grok"), never as the predicted winner. |
| 9 | - R4. get_x_source_status and get_x_source_with_method must prefer bird over xai/xurl/xquik when cookies are present. Grok wins only when the pin is grok. |
| 10 | - R5. Host docs stop presenting grok as the default keyless X path. Document it as opt-in backup. Default story is bird first, then xai / xurl / xquik. |
| 11 | - R6. Setup / first-run / prescriptions do not nag grok login as the fix for missing X. Cookie consent and paid keys remain the default prescriptions. Grok login is mentioned only as an optional pin. |
| 12 | - R7. Do not delete scripts/lib/grok_x.py, retrieve-judge-retry, or expires_at honesty. Pinned grok still uses them. |
| 13 | - R8. A machine with only a grok login (no cookies, no XAI/XQUIK, no xurl) has X unconfigured until the user pins grok. Footer: X skipped-unconfigured, not auth-failed-from-grok. |
| 14 | - R9. Tests cover the cases above; docs/changelog updated. |
| 15 | |
| 16 | ### Implementation units |
| 17 | U1 env.py: _X_BACKEND_ORDER = ("bird", "xai", "xurl", "xquik"); X_BACKEND_OPT_IN = ("grok",); X_BACKEND_KNOWN = ORDER + OPT_IN; pin uses KNOWN; unpinned walks ORDER only; get_x_source_status bird first, grok only if pinned; get_x_source_with_method bird before xai. |
| 18 | |
| 19 | U2 backends.py / doctor.py / prescriptions.py: descriptor is auto ORDER then grok opt-in; unpinned collect-then-pick ignores opt-in; do not change _probe_grok honesty. |
| 20 | |
| 21 | U3 SKILL.md, CONFIGURATION.md, README.md, README.pt-BR.md if needed, changelog.d: remove "sits ahead of the cookie path"; document bird → xai → xurl → xquik; pin grok to enable it. |
| 22 | |
| 23 | U4 tests: unpinned grok-only empty; unpinned grok+bird → bird; unpinned bird+xai → bird; pin grok+store → ["grok"]; pin grok no store empty; doctor unpinned never predicts grok; descriptor parity treats grok as trailing opt-in. |
| 24 | |
| 25 | ### Tests T1–T7 |
| 26 | T1 unpinned grok AUTH_OK, no other creds → X unconfigured |
| 27 | T2 unpinned grok AUTH_EXPIRED, no other creds → X unconfigured (not will-use grok) |
| 28 | T3 unpinned grok AUTH_OK + cookies → bird |
| 29 | T4 unpinned XAI_API_KEY + grok store, no cookies → xai |
| 30 | T4b unpinned XAI_API_KEY + cookies → bird |
| 31 | T5 pin grok AUTH_OK → grok no failover |
| 32 | T6 pin grok no store → error / grok login prescription |
| 33 | T7 docs match R5 |
| 34 | |
| 35 | ### Keep-the-door-open (KTD) |
| 36 | 1. grok_x.py stays untouched |
| 37 | 2. x_judge.py stays untouched |
| 38 | 3. expires_at honesty stays untouched |
| 39 | 4. auth.x.ai is never called |
| 40 | 5. bird cookie extraction is unchanged |
| 41 |