Add an opt-in Pro only policy: GPT-6 Pro, then GPT-5.6 Sol Pro, then stop #70

Merged
xicv merged 17 commits from feat/pro-ladder into main 2026-09-23 11:51:46 +00:00
xicv commented 2026-09-23 11:51:32 +00:00 (Migrated from github.com)

Summary

An opt-in "Pro only" model policy for ChatGPT's weekly GPT-6 Pro limit. Off unless model-policy.json in the data directory sets { "requirePro": true }; with it off, behaviour is unchanged.

Facts from OpenAI's help article and live, read-only checks on 2026-09-23:

  • Allowances. On Pro $200, GPT-6 Pro has 200 messages a week. GPT-5.6 Sol Pro has a separate 170 a day, and the two together are capped at 200 a day.
  • At the limit. "Latest" loses its Pro step and ChatGPT falls back to Medium ("Medium, 2 of 4."). A disabled "Pro" option appears. "GPT-5.6 Sol" still offers five levels.
  • Stale pages. A long-open page runs an older ChatGPT bundle that keeps showing Pro at the top of the slider after the limit, so the existing maximum repair is fooled.

With requirePro:

  • Reload before Send. Each exchange reloads Ego Chat's own chat page once, as a fenced mutation. The reload happens after the composer-surface, generation and foreign-draft checks, and is proven by a page marker that disappears and a newer performance.timeOrigin. The existing checks then run again on the new page. If the reload can't be proven, the run stops as the retryable policy_page_refresh_failed, bounded by the pre-Send retry budget.
  • Ladder.
    • Rung 1: the strongest option at a maximum named Pro (GPT-6 Pro).
    • Rung 2: exactly "GPT-5.6 Sol" at "Pro, N of N" (Sol Pro).
    • Otherwise the new human-only pro_model_unavailable_before_send, which is reconcilable to delivery absent. An unreadable Power description also stops.
  • Pinned readback. The final check before the click is pinned to the chosen option's label and a Pro maximum. A change clears the draft and stops with no Send.
  • Effort state. A Sol Pro send records effortState: "pro_fallback".
  • Alerts. model_pro_fallback fires once per episode. The per-chat downgrade notification is silent only for the planned gpt-5-6-pro answer.
  • Pause policy. Under answeringModelPolicy: "pause", a GPT-6 Pro to GPT-5.6 Sol Pro change no longer pauses.

Browser contract 32, runtime generation 2026-09-23.9. The design was discussed with Codex before implementation; its changes are in:

  • reload placement;
  • an explicit opt-in instead of inferring from history;
  • the pinned route;
  • the accepted answering-model list for pauses.

Verification

  • npm test: 1331 tests, 1330 pass, 1 skipped. Receipt suite 16/16. cargo test 33 + 1. ESLint clean on changed files.
  • Codex review (codex review --base origin/main, read-only): no actionable regression.
  • The DOM fixtures are built from the live states: before the limit, at the limit with the disabled "Pro" option, Sol with 5 levels, and the stale old-bundle page.

Live checks after install

A short exchange on a test binding will confirm:

  • that the same-URL Page.navigate reloads the document;
  • that Sol's top level reads "Pro, 5 of 5.";
  • that the run fits inside the Send deadline.

If the reload can't be proven live, requirePro stays off.

## Summary An opt-in "Pro only" model policy for ChatGPT's weekly GPT-6 Pro limit. Off unless `model-policy.json` in the data directory sets `{ "requirePro": true }`; with it off, behaviour is unchanged. Facts from OpenAI's help article and live, read-only checks on 2026-09-23: - **Allowances.** On Pro $200, GPT-6 Pro has 200 messages a week. GPT-5.6 Sol Pro has a separate 170 a day, and the two together are capped at 200 a day. - **At the limit.** "Latest" loses its Pro step and ChatGPT falls back to Medium ("Medium, 2 of 4."). A disabled "Pro" option appears. "GPT-5.6 Sol" still offers five levels. - **Stale pages.** A long-open page runs an older ChatGPT bundle that keeps showing Pro at the top of the slider after the limit, so the existing maximum repair is fooled. With `requirePro`: - **Reload before Send.** Each exchange reloads Ego Chat's own chat page once, as a fenced mutation. The reload happens after the composer-surface, generation and foreign-draft checks, and is proven by a page marker that disappears and a newer `performance.timeOrigin`. The existing checks then run again on the new page. If the reload can't be proven, the run stops as the retryable `policy_page_refresh_failed`, bounded by the pre-Send retry budget. - **Ladder.** - Rung 1: the strongest option at a maximum named Pro (GPT-6 Pro). - Rung 2: exactly "GPT-5.6 Sol" at "Pro, N of N" (Sol Pro). - Otherwise the new human-only `pro_model_unavailable_before_send`, which is reconcilable to delivery absent. An unreadable Power description also stops. - **Pinned readback.** The final check before the click is pinned to the chosen option's label and a Pro maximum. A change clears the draft and stops with no Send. - **Effort state.** A Sol Pro send records `effortState: "pro_fallback"`. - **Alerts.** `model_pro_fallback` fires once per episode. The per-chat downgrade notification is silent only for the planned `gpt-5-6-pro` answer. - **Pause policy.** Under `answeringModelPolicy: "pause"`, a GPT-6 Pro to GPT-5.6 Sol Pro change no longer pauses. Browser contract 32, runtime generation 2026-09-23.9. The design was discussed with Codex before implementation; its changes are in: - reload placement; - an explicit opt-in instead of inferring from history; - the pinned route; - the accepted answering-model list for pauses. ## Verification - `npm test`: 1331 tests, 1330 pass, 1 skipped. Receipt suite 16/16. `cargo test` 33 + 1. ESLint clean on changed files. - Codex review (`codex review --base origin/main`, read-only): no actionable regression. - The DOM fixtures are built from the live states: before the limit, at the limit with the disabled "Pro" option, Sol with 5 levels, and the stale old-bundle page. ## Live checks after install A short exchange on a test binding will confirm: - that the same-URL `Page.navigate` reloads the document; - that Sol's top level reads "Pro, 5 of 5."; - that the run fits inside the Send deadline. If the reload can't be proven live, `requirePro` stays off.
Sign in to join this conversation.
No description provided.