Skip to content

[codex] Add client failure reporting and visible surfacing#27

Draft
anantham wants to merge 3 commits intomainfrom
fix/codex-telemetry-ux
Draft

[codex] Add client failure reporting and visible surfacing#27
anantham wants to merge 3 commits intomainfrom
fix/codex-telemetry-ux

Conversation

@anantham
Copy link
Copy Markdown
Owner

@anantham anantham commented Apr 2, 2026

Summary

This PR closes the immediate silent-failure gaps in the reader and lays down the first client telemetry path for production debugging. It makes known and unexpected translation failures visible to users, records the failure type at the store boundary, and adds a Vercel callback proof for best-effort client telemetry.

Root Cause

Translation failures could disappear in production because three paths were incomplete:

  • the shared trial banner visibility check was inverted, so trial users could miss the banner entirely
  • store-backed notifications were written but never rendered
  • auto-translate fired a promise without a catch path, so unexpected failures could look like a hang instead of a surfaced error

A post-review regression surfaced at the async boundary:

  • MainApp assumed handleTranslate() always returned a thenable and chained .catch() directly
  • the integration test exposed that sync or mock implementations returning undefined broke that assumption

Changes

  • MainApp.tsx: mount NotificationToast once at the app root, catch unexpected auto-translate failures, and normalize the handleTranslate() boundary through Promise.resolve().then(...)
  • components/DefaultKeyBanner.tsx: fix shared-trial banner visibility and emit visible render telemetry
  • components/NotificationToast.tsx: add the missing notification renderer
  • components/ChapterView.tsx and components/chapter/ChapterContent.tsx: carry error telemetry into the reader surface and emit ui_error_rendered
  • services/clientTelemetry.ts and types/telemetry.ts: add the v1 client telemetry contract, redacting transport, and callback/analytics routing
  • services/telemetryService.ts: forward early boot errors, uncaught exceptions, and unhandled rejections into the client telemetry path
  • services/ai/apiKeyValidation.ts, services/translationService.ts, store/slices/translationsSlice.ts, store/slices/uiSlice.ts, store/slices/chaptersSlice.ts: classify translation failures and propagate structured telemetry metadata through the store
  • api/client-telemetry.js: add the Vercel callback proof handler
  • tests/store/appScreen.integration.test.tsx: align the mocked handleTranslate() contract with the async store API
  • Rebased branch onto current main to pick up ff5d821 and 54d4279
  • tests + docs: add regression coverage and document deployed callback verification plus post-review verification notes

Testing

  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vitest run tests/store/appScreen.integration.test.tsx
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vitest run tests/db/migrations/fresh-install.test.ts
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vitest run tests/services/navigationService.test.ts
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vitest run tests/components/NotificationToast.test.tsx tests/components/DefaultKeyBanner.test.tsx tests/components/chapter/ChapterContent.test.tsx tests/current-system/translation.test.ts tests/services/clientTelemetry.test.ts tests/services/api-key-validation.test.ts tests/api/client-telemetry.test.ts
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vitest run tests/smoke/critical-components.smoke.test.tsx
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npm run build
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vercel build
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vercel curl /api/client-telemetry --deployment https://codex-telemetry-fa9kmjyhm-adityas-projects-9c03351d.vercel.app
  • export PATH="$HOME/.nvm/versions/node/v22.17.0/bin:$PATH" && npx vercel curl /api/client-telemetry --deployment https://codex-telemetry-fa9kmjyhm-adityas-projects-9c03351d.vercel.app -- --request POST --header 'content-type: application/json' --data '{"event_type":"translation_failed"}'
  • Mixed-suite note: the large combined Vitest command still produced timeout-shaped failures in appScreen.integration and the smoke import, but both files passed immediately in isolated reruns after rebase. fresh-install and navigationService were green in the combined run, confirming the original branch-skew failures are resolved.

Review Checklist

  • Non-trivial change stays on feature branch fix/codex-telemetry-ux
  • Diff is scoped to the telemetry/visibility slice plus the post-review async-boundary fix
  • No vercel.json rewrite change was made because the deployed proof showed /api/client-telemetry is not shadowed by the SPA rewrite
  • Branch is rebased onto current main
  • Ready for Codex review

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexicon-forge Ready Ready Preview, Comment Apr 3, 2026 1:51am

anantham added 3 commits April 2, 2026 21:46
Context:
- translation failures could disappear in production because banner visibility, notification rendering, and fire-and-forget auto-translate handling were incomplete
- the Vercel callback path needed proof before expanding client telemetry coverage

Changes:
- fix shared trial banner visibility and add a notification toast renderer with a single app-level mount
- add the v1 client telemetry contract, redacting transport, global error forwarding, and classified translation failure emission
- add a Vercel /api/client-telemetry proof handler with deployment notes and route verification
- add regression and telemetry coverage for banner visibility, inline error rendering, callback validation, and translation classification

Impact:
- known and unexpected client failures are visible and measurable instead of failing silently
- unexpected auto-translate promise failures now surface in UI and telemetry
- the current Vite catch-all rewrite is proven not to shadow /api/client-telemetry

Tests:
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vitest run tests/components/NotificationToast.test.tsx tests/components/DefaultKeyBanner.test.tsx tests/components/chapter/ChapterContent.test.tsx tests/current-system/translation.test.ts tests/services/clientTelemetry.test.ts tests/services/api-key-validation.test.ts
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npm run build
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vercel build
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vercel curl /api/client-telemetry --deployment https://codex-telemetry-fa9kmjyhm-adityas-projects-9c03351d.vercel.app
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vercel curl /api/client-telemetry --deployment https://codex-telemetry-fa9kmjyhm-adityas-projects-9c03351d.vercel.app -- --request POST --header 'content-type: application/json' --data '{"event_type":"translation_failed"}'

Docs:
- docs/WORKLOG.md
- docs/guides/DEPLOYMENT.md
Context:
- MainApp assumed handleTranslate returned a thenable and chained .catch() directly
- appScreen.integration.test.tsx exposed that the boundary throws when a mock or sync implementation returns undefined

Changes:
- normalize the auto-translate call through Promise.resolve().then(...) so sync throws, undefined returns, and real promises share the same catch path
- update the integration test mock to reflect the intended async handleTranslate contract

Impact:
- auto-translate error handling is robust at the async boundary
- appScreen integration tests no longer fail on the same regression pattern

Tests:
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vitest run tests/store/appScreen.integration.test.tsx
Context:
- the post-review checklist required a real async-boundary fix, a rebase onto current main, and updated verification notes
- WORKLOG needed the rebase result and the distinction between real regressions and mixed-suite timeout noise

Changes:
- record the MainApp promise-normalization fix and the aligned appScreen integration mock
- document the successful rebase onto origin/main and the single worklog conflict resolution
- log the post-rebase targeted test outcomes, including isolated reruns for the timeout-shaped mixed-suite failures

Impact:
- future review can distinguish resolved regressions from test-runner contention artifacts without rediscovering them

Tests:
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vitest run tests/store/appScreen.integration.test.tsx
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npx vitest run tests/smoke/critical-components.smoke.test.tsx
- export PATH="/Users/aditya/.nvm/versions/node/v22.17.0/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/opt/homebrew/bin:/Users/aditya/.codex/tmp/arg0/codex-arg0pDiON6:/Users/aditya/.antigravity/antigravity/bin:/Users/aditya/bin:/Users/aditya/.claude/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/Users/aditya/.local/bin:/Users/aditya/.nvm/versions/node/v22.17.0/bin:/Applications/Codex.app/Contents/Resources" && npm run build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant