Skip to content

feat(codex): unify ChatGPT subscription onto pi-ai's openai-codex-responses wire#155

Merged
hqhq1025 merged 1 commit intomainfrom
worktree-codex-chatgpt-oauth
Apr 22, 2026
Merged

feat(codex): unify ChatGPT subscription onto pi-ai's openai-codex-responses wire#155
hqhq1025 merged 1 commit intomainfrom
worktree-codex-chatgpt-oauth

Conversation

@hqhq1025
Copy link
Copy Markdown
Collaborator

Summary

Phase 2 of the Codex ChatGPT subscription login. Phase 1 shipped a self-rolled client (SSE parser, ChatGPT headers, JWT accountId extraction, 401 retry) behind a "coming soon" UI gate. pi-ai 0.67.68 ships all of that as a first-class openai-codex-responses wire, so this PR deletes our version and routes ChatGPT subscription through the same core → pi-agent-core → pi-ai path every other provider already uses.

  • Link unified: no more isChatgptCodex branches. generate / generateTitle / applyComment all resolve codex exactly like Anthropic or OpenAI — the only codex-specific code left is the OAuth login flow (oauth.ts / oauth-server.ts / token-store.ts), and that sits outside the generation link.
  • Long-agent-run safety: GenerateInput.getApiKey is a new optional async getter; the desktop passes it for codex so pi-agent-core re-reads the token between turns (auto-refreshing within the token store's 5-min buffer). Mid-run sign-out errors propagate the original CodesignError(PROVIDER_AUTH_MISSING) rather than being flattened into a plain PROVIDER_ERROR.
  • Upgrade migration: boot-time migrateStaleCodexEntryIfNeeded() rewrites any Phase-1-shaped provider entry so feat-branch testers don't need to sign out/in.
  • UI flipped out of coming-soon: ChatgptLoginCard returns to the three-state login/status/logout flow with i18n in both locales.

Net diff: +758 / −1104, mostly deletions of Phase 1 self-rolled code pi-ai now provides.

PRINCIPLES §5b

  • Compatibility — old API-key configs unchanged; Phase 1 codex entries auto-migrate on boot
  • Upgradeability — CHATGPT_CODEX_PROVIDER_ID + WireApi live in @open-codesign/shared so future wire additions are one-line changes; OAuth provider entry is system-managed (rewritten idempotently on login/migrate)
  • No bloat — deletes 963 LOC of duplicated SSE/header/retry; adds 758 LOC (most of which is tests + the OAuth flow that was already there)
  • Elegance — one generateViaAgent code path for every provider; no provider-specific dispatch branches

Test plan

  • pnpm -r typecheck — green
  • pnpm -r test1289 tests pass across 10 packages (+11 new tests: base-url codex behavior, resolve-api-key DI helper, migrateStaleCodexEntryIfNeeded fork, agent.ts per-turn getApiKey + capture/rethrow)
  • pnpm lint — green
  • Manual smoke: sign-in flow, generate with codex active, switch back to API-key provider mid-run
  • Manual smoke: sign out mid-long-agent-run → confirm PROVIDER_AUTH_MISSING toast (not generic PROVIDER_ERROR)

Commits

  1. b8bb1b2 Main implementation — delete self-rolled client, register pi-ai wire, flip UI
  2. 375b9c5 First review pass — WireApi dedup, structured auth error, modelsHint ordering, +4 tests
  3. dde3bf3 Second pass — migration, CHATGPT_CODEX_PROVIDER_ID shared, resolve-api-key DI + 7 tests, per-turn getApiKey
  4. 8c443b9 Third pass — capture+rethrow so mid-agent-run auth errors preserve their structured code; +3 agent tests
  5. 412f159 Fourth pass — remove dead comingSoon i18n key, update changeset
  6. 296ac25 Drop obsolete internal Phase 2 resume doc

Known follow-ups (not blocking)

  • Usage / cost tracking for codex responses (pi-ai's codex wire emits usage events; complete() in packages/providers already surfaces them via GenerateResult, but the desktop UI's cost display still reads zero because Phase 1 hardcoded it).
  • Image-attachment support — pi-ai's wire accepts image input blocks; the complete() shim currently only forwards text. Tracked separately.

@github-actions github-actions Bot added docs Documentation area:desktop apps/desktop (Electron shell, renderer) area:core packages/core (generation orchestration) area:providers packages/providers (pi-ai adapter, model calls) labels Apr 22, 2026
Comment thread packages/shared/src/base-url.ts Fixed
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Hardcoded UI values in the new ChatGPT login badge violate the token-only UI constraint and will be hard to keep visually consistent across themes, evidence apps/desktop/src/renderer/src/components/ChatgptLoginCard.tsx:153.
    Suggested fix:

    <span className="inline-flex items-center gap-[var(--space-1)] px-[var(--space-1_5)] py-[var(--space-0_5)] rounded-full border border-[var(--color-accent)] text-[var(--color-accent)] bg-transparent text-[var(--font-size-badge)] font-medium leading-none">
      <Sparkles className="w-[var(--icon-xs)] h-[var(--icon-xs)]" />
    </span>
  • [Major] New helper intentionally swallows non-codex credential read failures and returns an empty key, which is a silent fallback (policy says errors must surface or throw with context), evidence apps/desktop/src/main/resolve-api-key.ts:41 and lock-in test apps/desktop/src/main/resolve-api-key.test.ts:78.
    Suggested fix:

    try {
      return deps.getApiKeyForProvider(providerId);
    } catch (err) {
      throw new CodesignError(
        `Failed to read API key for provider "${providerId}"`,
        ERROR_CODES.PROVIDER_AUTH_MISSING,
        { cause: err },
      );
    }

Summary

  • Review mode: initial
  • 2 issues found (2 Major), both on added/modified lines.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs in this checkout.

Testing

  • Not run (automation)

open-codesign Bot

return (
<div className="rounded-[var(--radius-lg)] border border-[var(--color-border)] border-l-[var(--size-accent-stripe)] border-l-[var(--color-accent)] bg-[var(--color-accent-tint)] px-[var(--space-3)] py-[var(--space-2_5)] flex items-center gap-[var(--space-3)]">
<div className="min-w-0 flex-1 flex items-center gap-2 flex-wrap">
<span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full border border-[var(--color-accent)] text-[var(--color-accent)] bg-transparent text-[var(--font-size-badge)] font-medium leading-none">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded utility values (gap-1, px-1.5, py-0.5, plus w-2.5/h-2.5 nearby) bypass the token system. This conflicts with the token-only UI constraint and makes theme-scale consistency harder to maintain. Please replace these with existing UI token vars (or add missing tokens in packages/ui).

}
try {
return deps.getApiKeyForProvider(providerId);
} catch {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This catch returns '' for any non-codex credential read failure, which is a silent fallback. The project constraint requires surfacing/throwing errors with context. Please rethrow a structured CodesignError with cause instead of swallowing here.

@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from f7cb805 to 1e4e9a7 Compare April 22, 2026 10:28
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Hardcoded UI values in the new ChatGPT login badge violate the token-only UI constraint and will drift from theme/system scales, evidence apps/desktop/src/renderer/src/components/ChatgptLoginCard.tsx:153.
    Suggested fix:

    <span className="inline-flex items-center gap-[var(--space-1)] px-[var(--space-1_5)] py-[var(--space-0_5)] rounded-full border border-[var(--color-accent)] text-[var(--color-accent)] bg-transparent text-[var(--font-size-badge)] font-medium leading-none">
      <Sparkles className="w-[var(--icon-xs)] h-[var(--icon-xs)]" />
      {t('settings.providers.chatgptLogin.loggedInBadge')}
    </span>
  • [Major] resolveActiveApiKey silently swallows non-codex credential read failures and returns an empty key, which violates the no-silent-fallback constraint and hides keychain/config errors, evidence apps/desktop/src/main/resolve-api-key.ts:41.
    Suggested fix:

    try {
      return deps.getApiKeyForProvider(providerId);
    } catch (err) {
      throw new CodesignError(
        `Failed to read API key for provider "${providerId}"`,
        ERROR_CODES.PROVIDER_AUTH_MISSING,
        { cause: err },
      );
    }

Summary

  • Review mode: follow-up after new commits
  • 2 issues found (2 Major), both on added/modified lines in this head.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation)

open-codesign Bot

return (
<div className="rounded-[var(--radius-lg)] border border-[var(--color-border)] border-l-[var(--size-accent-stripe)] border-l-[var(--color-accent)] bg-[var(--color-accent-tint)] px-[var(--space-3)] py-[var(--space-2_5)] flex items-center gap-[var(--space-3)]">
<div className="min-w-0 flex-1 flex items-center gap-2 flex-wrap">
<span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full border border-[var(--color-accent)] text-[var(--color-accent)] bg-transparent text-[var(--font-size-badge)] font-medium leading-none">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Token-only UI constraint: this new badge uses hardcoded scale values (gap-1, px-1.5, py-0.5, w-2.5/h-2.5). Please switch these to token vars (or add missing tokens in packages/ui) to keep sizing/theme consistency.

);
}
}
try {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This catch returns `` for any non-codex key-read error, which is a silent fallback. Please throw a structured CodesignError with context/cause so keychain/config failures surface explicitly.

@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from 1e4e9a7 to 274bf90 Compare April 22, 2026 10:37
@hqhq1025
Copy link
Copy Markdown
Collaborator Author

Addressed both Major findings:

1. Hardcoded UI values (ChatgptLoginCard.tsx:153) — replaced gap-1 / px-1.5 / py-0.5 / w-2.5 / w-3.5 / mt-0.5 Tailwind numeric literals with the corresponding var(--space-*) / var(--size-icon-*) tokens from packages/ui/src/tokens.css. Both the logged-in badge view and the signed-out view now go through tokens, matching the rule in CLAUDE.md ("UI must use packages/ui tokens"). font-size-badge is preserved as-is — it's the same referenced-but-undefined token used by Settings.tsx:336/341/356 for consistent badge typography; adding it is a separate UI design decision, so I left it matching existing call sites.

2. Silent fallback in resolveActiveApiKey — the helper no longer swallows non-codex failures. It now wraps any underlying throw in CodesignError(PROVIDER_AUTH_MISSING) with the original attached as cause, and passes through a pre-existing CodesignError untouched. Keyless-provider support (Ollama, IP-gated LiteLLM) moved to a new resolveApiKeyForActive(providerId, allowKeyless) wrapper at the IPC layer that only swallows PROVIDER_AUTH_MISSING when both allowKeyless is true AND the provider is not the codex OAuth flow. Any real failure (codex logout, keychain corruption) now propagates to the renderer with a structured code — no silent drops.

Test updates: replaced the two "returns empty string" tests with three covering the new shape — wrap-with-cause, pass-through-existing-CodesignError, and non-Error rejection fallback. 1295 tests across 10 packages pass; pnpm typecheck / pnpm lint green.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Keyless providers regress to hard failure because PROVIDER_KEY_MISSING is no longer swallowed in the new keyless path. resolveActiveApiKey now passes through existing CodesignErrors (including PROVIDER_KEY_MISSING from onboarding), but resolveApiKeyForActive only swallows PROVIDER_AUTH_MISSING; this breaks requiresApiKey: false providers on generate/apply/title despite allowKeyless=true, evidence apps/desktop/src/main/index.ts:187, apps/desktop/src/main/resolve-api-key.ts:49, apps/desktop/src/main/onboarding-ipc.ts:150.
    Suggested fix:
    // apps/desktop/src/main/index.ts
    if (
      allowKeyless &&
      providerId !== CHATGPT_CODEX_PROVIDER_ID &&
      err instanceof CodesignError &&
      (err.code === ERROR_CODES.PROVIDER_AUTH_MISSING ||
        err.code === ERROR_CODES.PROVIDER_KEY_MISSING)
    ) {
      return '';
    }

Summary

  • Review mode: follow-up after new commits
  • 1 issue found (1 Major).
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.
  • Residual risk: no regression test currently asserts keyless providers still proceed when secret lookup throws PROVIDER_KEY_MISSING.

Testing

  • Not run (automation)

open-codesign Bot

Comment thread apps/desktop/src/main/index.ts Outdated
allowKeyless &&
providerId !== CHATGPT_CODEX_PROVIDER_ID &&
err instanceof CodesignError &&
err.code === 'PROVIDER_AUTH_MISSING'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keyless fallback now only swallows PROVIDER_AUTH_MISSING, but resolveActiveApiKey passes through PROVIDER_KEY_MISSING from getApiKeyForProvider. For allowKeyless providers this turns missing secret into a hard failure. Please also swallow PROVIDER_KEY_MISSING here (non-codex only).

@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from 274bf90 to 63394b3 Compare April 22, 2026 10:44
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Keyless providers still fail hard on missing stored secret — resolveActiveApiKey now preserves CodesignError(PROVIDER_KEY_MISSING), but keyless fallback in resolveApiKeyForActive only swallows PROVIDER_AUTH_MISSING; providers with requiresApiKey: false can regress from keyless flow to blocking error, evidence apps/desktop/src/main/index.ts:187, apps/desktop/src/main/resolve-api-key.ts:49, apps/desktop/src/main/onboarding-ipc.ts:148.
    Suggested fix:
    if (
      allowKeyless &&
      providerId !== CHATGPT_CODEX_PROVIDER_ID &&
      err instanceof CodesignError &&
      (err.code === ERROR_CODES.PROVIDER_AUTH_MISSING ||
        err.code === ERROR_CODES.PROVIDER_KEY_MISSING)
    ) {
      return '';
    }

Summary

  • Review mode: follow-up after new commits
  • 1 issue found (1 Major).
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.
  • Residual risk/testing gap: no integration test in this PR asserts that requiresApiKey: false providers continue with empty bearer when secret lookup throws PROVIDER_KEY_MISSING.

Testing

  • Not run (automation)

open-codesign Bot

Comment thread apps/desktop/src/main/index.ts Outdated
allowKeyless &&
providerId !== CHATGPT_CODEX_PROVIDER_ID &&
err instanceof CodesignError &&
err.code === 'PROVIDER_AUTH_MISSING'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keyless fallback here still only handles PROVIDER_AUTH_MISSING. Since resolveActiveApiKey now passes through PROVIDER_KEY_MISSING, requiresApiKey: false providers can fail hard instead of proceeding with empty bearer. Please include PROVIDER_KEY_MISSING in the swallow condition for non-codex providers.

@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from 63394b3 to 6a8dd59 Compare April 22, 2026 10:49
@hqhq1025
Copy link
Copy Markdown
Collaborator Author

Fixed. Real regression — getApiKeyForProvider throws CodesignError(PROVIDER_KEY_MISSING) (not PROVIDER_AUTH_MISSING), resolveActiveApiKey passes existing CodesignErrors through untouched, and the keyless wrapper only swallowed PROVIDER_AUTH_MISSING. Ollama / requiresApiKey: false providers would hard-fail on generate despite allowKeyless=true.

Widened the keyless-swallow to accept both missing-credential codes, and moved the wrapper into resolve-api-key.ts as resolveApiKeyWithKeylessFallback so the main-process resolveApiKeyForActive is now a 3-line DI shim. Added 6 regression tests covering:

  • Keyless Ollama with PROVIDER_KEY_MISSING → returns ''
  • Keyless proxy with wrapped PROVIDER_AUTH_MISSING → returns ''
  • Keyless provider with unrelated code (PROVIDER_ERROR) → propagates verbatim
  • Non-keyless provider with PROVIDER_KEY_MISSING → rethrows so user sees "add your key"
  • Codex is NEVER swallowed even if a hand-edited config marks the entry keyless
  • Happy path

14 tests in resolve-api-key.test.ts (was 8), 1301 tests total pass across 10 packages; pnpm typecheck / pnpm lint green.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Silent fallback hides ChatGPT OAuth status failures — the status bootstrap catch path suppresses the error and renders a logged-out state, so auth/backend failures are not surfaced to users and violate the no-silent-fallback constraint, evidence apps/desktop/src/renderer/src/components/ChatgptLoginCard.tsx:105.
    Suggested fix:
    useEffect(() => {
      if (!window.codesign) return;
      void window.codesign.codexOAuth
        .status()
        .then((s) => {
          if (mountedRef.current) setStatus(s);
        })
        .catch((err) => {
          if (mountedRef.current) setStatus(null);
          pushToast({
            variant: 'error',
            title: t('settings.providers.chatgptLogin.statusFailedTitle'),
            description: err instanceof Error ? err.message : t('settings.providers.chatgptLogin.unknownError'),
          });
        });
    }, [pushToast, t]);

Summary

  • Review mode: follow-up after new commits
  • 1 issue found (1 Major).
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation). Suggested: add a ChatgptLoginCard unit test asserting a toast is emitted when codexOAuth.status() rejects.

open-codesign Bot

.then((s) => {
if (mountedRef.current) setStatus(s);
})
.catch(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This catch path currently swallows OAuth/status failures and silently downgrades to not-logged-in. Please surface the error (toast or inline state) so failures are visible instead of falling back quietly.

@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from 6a8dd59 to 63920cb Compare April 22, 2026 11:00
@hqhq1025
Copy link
Copy Markdown
Collaborator Author

Fixed. The useEffect status bootstrap had a bare .catch(() => setStatus(null)) that rendered a logged-out UI regardless of whether the user is genuinely signed out or the IPC backend / keychain failed — the bot correctly flagged this as a silent-fallback violation.

Extracted the fetch into a testable performFetchStatus(deps) helper (same DI pattern as performLogin / performLogout) and pointed the effect at it. On reject: setStatus(null) still fires so the UI doesn't get stuck on stale data, but now a toast with settings.providers.chatgptLogin.statusFailedTitle + the underlying error message surfaces through the existing toast channel. Unmount guard is preserved.

Added 5 unit tests in ChatgptLoginCard.test.tsx:

  • IPC resolves → setStatus called, no toast
  • IPC rejects → setStatus(null) + error toast with description from err.message
  • Unmounted before resolve → neither side-effect fires
  • Unmounted before reject → neither side-effect fires
  • Non-Error rejection → toast uses the unknownError fallback string

1306 tests total pass; pnpm typecheck / pnpm lint green.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Boot migration failure is silently downgraded to a log warning — this violates the “no silent fallbacks” constraint and can leave stale codex provider config unresolved without any user-visible signal, evidence apps/desktop/src/main/index.ts:1051.
    Suggested fix:
    // Prefer surfacing migration failure to the existing boot error dialog path.
    await migrateStaleCodexEntryIfNeeded();

Summary

  • Review mode: follow-up after new commits
  • 1 issue found (1 Major).
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation).

open-codesign Bot

Comment thread apps/desktop/src/main/index.ts Outdated
try {
await migrateStaleCodexEntryIfNeeded();
} catch (err) {
getLogger('main').warn('boot.migrate_stale_codex_failed', {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Major] This catch path turns migration failures into a log-only warning. That is a silent fallback for users and can leave stale wire/baseUrl in place with no visible remediation path. Please let this throw into the existing boot error handling flow (or surface a user-visible error) instead of swallowing it.

…ponses wire

Phase 2 of the Codex ChatGPT subscription login. Phase 1 shipped a
self-rolled client (SSE parser, ChatGPT headers, JWT accountId
extraction, 401 retry) behind a "coming soon" UI gate. pi-ai 0.67.68
ships all of that as a first-class `openai-codex-responses` wire, so
this deletes our version and routes ChatGPT subscription through the
same `core → pi-agent-core → pi-ai` path every other provider uses.

## Schema + routing
- `packages/shared`: extend `WireApiSchema` and `CanonicalWire` with
  `openai-codex-responses`; promote `CHATGPT_CODEX_PROVIDER_ID` to
  shared so `provider-settings` and the OAuth module reference the same
  literal without a module cycle.
- `canonicalBaseUrl` passes codex URLs through untouched (pi-ai's wire
  appends `/codex/responses` itself); `modelsEndpointUrl` throws for
  codex (no discoverable /models endpoint — providers use modelsHint).
- `packages/core`, `packages/providers`: `apiForWire` +
  `synthesizeWireModel` recognize the new wire; the 4 duplicated
  `'openai-chat' | …` unions consolidated onto the shared `WireApi`.

## Desktop wiring
- New `apps/desktop/src/main/resolve-api-key.ts`: DI helper that routes
  ChatGPT provider id to the token store's auto-refreshing access
  token, other providers to the keychain-backed API key. Codex auth
  failures surface as `CodesignError(PROVIDER_AUTH_MISSING)` for
  consistent renderer error-code routing. 7 unit tests cover the fork.
- `main/index.ts`: `resolveActiveApiKeyFromState` replaces the inline
  `isChatgptCodex` validate / dispatch branches in all 4 IPC handlers.
  Legacy `codesign:generate` no longer rejects codex.
- Long agent runs: `GenerateInput.getApiKey` is a new optional async
  getter; the desktop passes it only for codex so pi-agent-core calls
  back into the token store on each LLM round-trip (auto-refreshes
  within the 5-min buffer). Mid-run sign-out errors are captured in a
  closure and rethrown from the post-agent branch so the structured
  PROVIDER_AUTH_MISSING code survives pi-agent-core's plain-string
  failure-message flattening.

## Registration + migration
- `codex-oauth-ipc.ts`: provider entry registers
  `wire=openai-codex-responses`, bare
  `baseUrl=https://chatgpt.com/backend-api`, and the full 9-model
  catalog (gpt-5.1 → gpt-5.4-mini), flagship-first.
- `migrateStaleCodexEntryIfNeeded()` runs once at boot and rewrites any
  Phase-1-shaped entry so feat-branch testers don't need to sign out
  and back in. No-op when the entry is absent or already canonical.

## UI
- `ChatgptLoginCard.tsx`: flipped out of "coming soon" mode back to the
  full login/status/logout flow with i18n in both locales.

## Deletions (~963 LOC of Phase 1 code now provided by pi-ai)
- `apps/desktop/src/main/codex-generate.ts` + test
- `apps/desktop/src/main/codex-title.ts`
- `packages/providers/src/codex/client.ts` + test

OAuth-side code (`oauth.ts`, `oauth-server.ts`, `token-store.ts`) is
unchanged — still the only codex-specific code, and it sits outside
the generation link.

pnpm -r typecheck, 1293 tests across 10 packages, and pnpm lint all green.

Signed-off-by: hqhq1025 <[email protected]>
@hqhq1025 hqhq1025 force-pushed the worktree-codex-chatgpt-oauth branch from 63920cb to 79c064f Compare April 22, 2026 11:07
@hqhq1025
Copy link
Copy Markdown
Collaborator Author

Fixed. Removed the try { … } catch (err) { logger.warn(…) } wrapper around migrateStaleCodexEntryIfNeeded() in the boot sequence. A migration failure means writeConfig can't persist — that's serious enough that the existing outer app.whenReady() try/catch + handleBootFailure dialog is the correct surface; swallowing with a log leaves the user with a mysteriously broken codex flow and nothing to act on.

pnpm typecheck / 1306 tests / pnpm lint green.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • No issues found in added/modified lines that meet the reporting confidence bar.

Summary

  • Review mode: follow-up after new commits
  • No new blocker/major/minor issues identified in the latest head diff.
  • Previously flagged silent-fallback risk is resolved: boot migration now bubbles failure into the existing boot-error dialog path (apps/desktop/src/main/index.ts:1055).
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.
  • Residual risk/testing gap: this PR removes many unit tests in apps/desktop/src/renderer/src/components/Settings.test.ts while inlining banner-branch logic in Settings.tsx, so those branches now rely more on integration behavior than direct unit coverage.

Testing

  • Not run (automation).

open-codesign Bot

@hqhq1025 hqhq1025 merged commit 4391788 into main Apr 22, 2026
7 checks passed
@hqhq1025 hqhq1025 deleted the worktree-codex-chatgpt-oauth branch April 22, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core packages/core (generation orchestration) area:desktop apps/desktop (Electron shell, renderer) area:providers packages/providers (pi-ai adapter, model calls) docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants