Skip to content

fix(gui): do not offer retry for the Grok coupon reset POST - #5103

Merged
lidge-jun merged 3 commits into
lidge-jun:devfrom
luvs01:fix/grok-coupon-no-retry
Sep 19, 2026
Merged

lidge-jun merged 3 commits into
lidge-jun:devfrom
luvs01:fix/grok-coupon-no-retry

Conversation

@luvs01

@luvs01 luvs01 commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

The Grok reset-coupon redeem POST is irreversible: once dispatched, the route may spend the coupon even if the client never sees the answer. The hook used to classify a generic transport rejection as network, a retryable failure — so a retry after a dropped response could post a second redemption and spend another coupon. Only an abort signal counted as an unknown outcome.

Description

  • useGrokResetCoupons: any rejection after dispatch now returns code: "aborted" — outcome unknown, delivery may have succeeded. The dialog holds the operation id, stops posting, and only lets the user re-read the account.
  • The wasAborted helper is removed: there is no safely retryable transport failure for this route.

Tests

  • bun test tests/grok-reset-coupons.test.tsx — 9 pass; the rejection case now asserts the unknown-outcome path rather than a retryable network error.
  • bun run typecheck — clean.

Screenshots

[Coupon dialog after a dropped redemption response: outcome unknown, posting blocked, re-read offered] (screenshot removed; was hosted on the contributor fork)

Summary by CodeRabbit

  • Bug Fixes
    • Redemption requests that fail during transport are now handled consistently as aborted outcomes.
    • Status messaging better reflects that a redemption may have completed even when its result cannot be delivered.
    • The previous network-specific redemption outcome is no longer reported.

A transport rejection after the redemption POST is dispatched has an unknown outcome: the request may still reach the server and spend the coupon. Classifying it as a retryable network error let the operator re-submit an irreversible redemption with the same operation id. Return the aborted outcome for any post-dispatch rejection so the UI stops posting and forces a re-read of account state.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: bd039527-9c42-4e31-bd02-01d03e58a893

📥 Commits

Reviewing files that changed from the base of the PR and between 7864869 and 257eaa5.

⛔ Files ignored due to path filters (1)
  • .github/pr-assets/508-grok-coupon-unknown.png is excluded by !**/*.png
📒 Files selected for processing (2)
  • gui/src/hooks/useGrokResetCoupons.ts
  • gui/tests/grok-reset-coupons.test.tsx

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The redemption hook now treats every transport rejection as an aborted outcome. The regression test uses a TypeError to verify that a rejected request still shows an unknown outcome and prevents reposting.

Changes

Grok redemption handling

Layer / File(s) Summary
Transport rejection outcome and regression coverage
gui/src/hooks/useGrokResetCoupons.ts, gui/tests/grok-reset-coupons.test.tsx
At lines 194–197, all transport rejections now return code: "aborted" instead of distinguishing network errors. The unused wasAborted helper was removed at line 104. The outcome documentation and final test were updated. The test now throws TypeError("connection reset after request dispatch") and keeps the existing assertions.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: lidge-j

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: the Grok coupon reset flow must not offer a retry after the redemption POST is rejected.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 19, 2026
@github-actions

github-actions Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • UI screenshot required.

What to do

  • Add a screenshot of the UI change to the PR description.

Automatic draft conversion failed (token cannot change draft status). Please convert this pull request to a draft manually. The required enforce-target check will keep failing until every issue above is resolved.

@github-actions
github-actions Bot marked this pull request as ready for review September 19, 2026 06:20
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 74 / 80

Grok reset-coupon redeem POST는 한 번 나가면 서버가 쿠폰을 쓸 수 있습니다. 클라이언트가 답을 못 받아도 이미 소비됐을 수 있습니다. 예전 훅은 일반 transport 거부를 network(재시도 가능)로 분류해서, 응답이 끊긴 뒤 재시도하면 두 번째 redeem이 나가 쿠폰이 또 깎일 수 있었습니다. abort만 unknown으로 취급했습니다.

이 PR은 dispatch 이후 어떤 rejection이든 code: "aborted"(결과 불명)로 돌립니다. 다이얼로그는 재POST를 막고 계정 재조회만 허용합니다. wasAborted 헬퍼는 삭제됐습니다. 이 라우트에는 안전한 retryable transport failure가 없다는 계약입니다. 테스트·스크린샷 에셋이 unknown-outcome UI를 고정합니다.

호스티드 CI는 test 1–3 그린, docker/macos/test4 일부 pending. types/config 스플릿과 무관. GUI 전용 좁은 수정입니다.

경로 useGrokResetCoupons.ts catch - 모든 거부를 aborted로. irreversible POST에 맞는 보수적 선택이다
삭제 wasAborted - network/aborted 이분법이 위험했던 원인이다
테스트 grok-reset-coupons.test.tsx - 재시도 금지 경로를 고정해야 한다(PR 설명 기준 9 pass)
에셋 .github/pr-assets/508-grok-coupon-unknown.png - 문서용. 동작과 무관
호스티드 CI - 남은 shard 그린 확인 후 merge

메인테이너의 판단이 필요한 지점

  • UI 카피가 “aborted”를 사용자에게 어떻게 보이는지(내부 code vs 문구)
  • 남은 CI shard만 기다릴지

너의 추천
남은 호스티드 CI가 그린이면 merge. 쿠폰 이중 소비는 사용자 피해가 커서 문서·draft보다 우선한다. types/config 스플릿으로 닫을 PR이 아니다.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun
lidge-jun merged commit fe2b755 into lidge-jun:dev Sep 19, 2026
35 of 36 checks passed
@luvs01
luvs01 deleted the fix/grok-coupon-no-retry branch September 20, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants