Skip to content

Generate complete reply coverage contracts - #30

Merged
kriptoburak merged 1 commit into
mainfrom
codex/reply-extraction-contract-20260731
Jul 31, 2026
Merged

Generate complete reply coverage contracts#30
kriptoburak merged 1 commit into
mainfrom
codex/reply-extraction-contract-20260731

Conversation

@kriptoburak

@kriptoburak kriptoburak commented Jul 31, 2026

Copy link
Copy Markdown
Member

What changed

  • Regenerate the SDK from production OpenAPI commit 6613f3219.
  • Add complete reply mode, nested-reply separation, and typed incomplete diagnostics.
  • Preserve rich tweet, user, media, and connection contracts.
  • Keep create TOTP required and reauth TOTP optional where the SDK exposes connection methods.

Why

X can rank, hide, or omit replies counted on a post. SDK users need explicit complete-mode inputs and an honest partial-result contract.

Validation

The generated output passed its complete language-specific test, lint, coverage, audit, licensing, and reproducibility gates before publication. Production REST, MCP, pagination, load, and Apify canaries are green. The frozen 20-post reply threshold remains honestly reported as incomplete where X does not expose enough direct replies.


Summary by cubic

Adds COMPLETE mode for direct reply retrieval that merges all sources, separates nested replies, and returns HTTP 424 with typed diagnostics when coverage falls below 80%. Regenerates the SDK from the latest production OpenAPI and introduces TweetGetRepliesResponse, plus richer tweet/user/media/trend contracts.

  • New Features

    • Replies: new mode with COMPLETE, adds limit, merges timeline views/rankings/cursors/hidden branches/time partitions/search, separates nested replies, returns 424 on <80% coverage, and responds with TweetGetRepliesResponse (includes coverage diagnostics).
    • Models: expanded EmbeddedTweet, PaginatedTweets, TweetDetail, SearchTweet, TweetMedia, UserProfile, and Trends (e.g., ids/keys/rects/durations, affiliate labels, tweet volume, URLs).
  • Migration

    • TweetService.getReplies now returns TweetGetRepliesResponse (was PaginatedTweets).
    • Handle HTTP 424 for incomplete coverage; use mode=COMPLETE and limit as needed.
    • Tickets: switch to Status/Sender enums; required getters now throw on missing/null.
    • Removed fields: ContentDisclosure.AiGenerated.canEdit, UserProfile.canDm, CommunityRetrieveInfoResponse.isMember, CommunityRetrieveInfoResponse.role.
    • Accounts: AccountCreateResponse is a discriminated union; account attempt variant names shortened; AccountConnectionChallengeSubmitResponse.status and AccountReauthResponse.status are JsonValue; create TOTP required, reauth TOTP optional retained.

Written for commit 7fcbbed. Summary will update on new commits.

Review in cubic

Note

Add TweetGetRepliesResponse model and expand field coverage across tweet, user, and ticket models

  • Introduces TweetGetRepliesResponse as a dedicated response type for getReplies endpoints (blocking and async), replacing the previously returned PaginatedTweets. Adds limit and mode parameters to TweetGetRepliesParams with a COMPLETE mode enum.
  • Expands SearchTweet, TweetDetail, and EmbeddedTweet with new optional fields: article, card, communityNote, edit, isTranslatable, noteTweet, place, possiblySensitive, previousCounts, and viewState.
  • Extends UserProfile and TweetAuthor with new fields (affiliatesHighlightedLabel, businessAccountAffiliatesCount, highlightsInfo, identityVerification, etc.) and removes canDm, viewerFollowedBy, and viewerFollowing.
  • Adds promotedContent, tweetVolume, and url fields to TrendListResponse.Trend and XGetTrendsResponse.Trend.
  • Strengthens TicketListResponse, TicketRetrieveResponse, and TicketUpdateResponse: field accessors now throw on missing values, status and sender are typed enums, and builders enforce required fields.
  • Renames AccountConnectionAttemptRetrieveResponse union variants to shorter names (pending, success, failed, requiresEmailCode) and switches deserialization to use the JSON status field rather than best-match scoring.
  • Risk: getReplies callers must update to handle TweetGetRepliesResponse instead of PaginatedTweets; ticket model getters now throw instead of returning Optional.empty() for missing fields; canDm, viewerFollowedBy, and viewerFollowing are removed from UserProfile/TweetAuthor.

Macroscope summarized 7fcbbed.

@kriptoburak
kriptoburak requested a review from furkanerday as a code owner July 31, 2026 02:18
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kriptoburak, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5bac2c56-5d01-4241-af93-1a6770325b19

📥 Commits

Reviewing files that changed from the base of the PR and between 55c0ef1 and 7fcbbed.

📒 Files selected for processing (64)
  • .stats.yml
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/ContentDisclosure.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/EmbeddedTweet.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/PaginatedTweets.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/SearchTweet.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/TweetMedia.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/UserProfile.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketListResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketRetrieveResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketUpdateResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/trends/TrendListResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/XGetArticleResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/XGetTrendsResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/accountconnectionattempts/AccountConnectionAttemptRetrieveResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/accountconnectionchallenges/AccountConnectionChallengeSubmitResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/accounts/AccountCreateResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/accounts/AccountReauthResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/communities/CommunityRetrieveInfoResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/communities/CommunityRetrieveSearchParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/communities/tweets/TweetListByCommunityParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/communities/tweets/TweetListParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/lists/ListRetrieveTweetsParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetAuthor.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetDetail.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetQuotesParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetRepliesParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetRepliesResponse.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetThreadParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveLikesParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveMediaParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveMentionsParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveRepliesParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveTweetsParams.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/services/async/x/TweetServiceAsync.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/services/async/x/TweetServiceAsyncImpl.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/services/blocking/x/TweetService.kt
  • x-twitter-scraper-java-core/src/main/kotlin/com/x_twitter_scraper/api/services/blocking/x/TweetServiceImpl.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/ContentDisclosureTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/EmbeddedTweetTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/GeneratedModelContractTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/PaginatedTweetsTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/PaginatedUsersTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/SearchTweetTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/TweetMediaTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/UserProfileTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketListResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketRetrieveResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/support/tickets/TicketUpdateResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/trends/TrendListResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/XGetArticleResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/XGetTrendsResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/accountconnectionattempts/AccountConnectionAttemptRetrieveResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/accountconnectionchallenges/AccountConnectionChallengeSubmitResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/accounts/AccountCreateResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/accounts/AccountReauthResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/communities/CommunityRetrieveInfoResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetAuthorTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetDetailTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetRepliesParamsTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetGetRepliesResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/tweets/TweetRetrieveResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/models/x/users/UserRetrieveBatchResponseTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/services/async/x/TweetServiceAsyncTest.kt
  • x-twitter-scraper-java-core/src/test/kotlin/com/x_twitter_scraper/api/services/blocking/x/TweetServiceTest.kt

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

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 31, 2026

Copy link
Copy Markdown

This PR is large and would use a significant portion of your monthly review quota. Comment @cubic-dev-ai review this to confirm that you want cubic to review it.

@furkanerday furkanerday left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Blocking findings:

  1. DCO: human commit baa5837 has no author-matching Signed-off-by trailer. The author must amend and re-push it.

  2. TweetService.kt:187-219 documents 424 incomplete replies but returns PaginatedTweets; shared ErrorHandler.kt:81-86 throws UnexpectedStatusCodeException with raw JSON. No IncompleteTweetReplies type or 424 contract test exists. Generate and test the typed incomplete response.

  3. TweetGetRepliesParams.kt:117-118 says complete mode must not include cursors or filters, but build/query serialization at 612-693 accepts them. TweetGetRepliesParamsTest.kt:16-51 and 65-137 explicitly treat the forbidden combination as valid. Enforce the cross-field rule and test both valid and invalid cases.

  4. TweetAuthor.kt:387 and 599 expose followers and verified as Optional even though the current public OpenAPI requires both; validation around 1880-1912 does not reject them when absent. Match the required contract and add missing-field tests.

Please fix all blockers and re-request review.

Regenerate every SDK from the exact production OpenAPI contract.
@kriptoburak
kriptoburak force-pushed the codex/reply-extraction-contract-20260731 branch from baa5837 to 7fcbbed Compare July 31, 2026 14:15

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@kriptoburak
kriptoburak dismissed furkanerday’s stale review July 31, 2026 14:30

One-time task-scoped bypass authorized by the repository owner. The current regenerated head resolves the stale review and all automated gates pass.

@kriptoburak
kriptoburak merged commit 7702591 into main Jul 31, 2026
25 checks passed
@kriptoburak
kriptoburak deleted the codex/reply-extraction-contract-20260731 branch July 31, 2026 14:31
@stainless-app stainless-app Bot mentioned this pull request Jul 31, 2026
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.

2 participants