From 6fb2aaa19f36ae7455c95f288a86818e53d9c2eb Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Mon, 14 Sep 2026 14:58:58 -0400 Subject: [PATCH] refactor(mobile): undo the github-pr-mutations split, which max-lines no longer forces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The split was made when the migrated file measured 319 lines. It does not any more: `sendRaw`, `sendGithubPrMutation` and `extractMutationError` moved to github-pr-mutation-outcome.ts and the prRepo/headSha allow-lists to github-pr-repo-slug.ts, so the merged file is 293 lines against the 300 limit and oxlint is clean. Nothing imported github-pr-comment-mutations directly — every consumer went through the re-export hub in github-pr-mutations — so the seam bought a reader one extra file to open and nothing else. Merge it back and drop the hub. Product-only: same wrappers, same params, same settle shapes, no golden moves. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb --- .../session/github-pr-comment-mutations.ts | 137 ----------------- mobile/src/session/github-pr-mutations.ts | 140 ++++++++++++++++-- 2 files changed, 129 insertions(+), 148 deletions(-) delete mode 100644 mobile/src/session/github-pr-comment-mutations.ts diff --git a/mobile/src/session/github-pr-comment-mutations.ts b/mobile/src/session/github-pr-comment-mutations.ts deleted file mode 100644 index 91c00c95210..00000000000 --- a/mobile/src/session/github-pr-comment-mutations.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { - githubPrIssueCommentAdd, - githubPrIssueCommentDelete, - githubPrIssueCommentEdit, - githubPrReviewCommentReplyAdd, - githubPrReviewThreadResolve -} from './github-pr-mutation-operations' -import { - settleGithubPrConfirmation, - settleGithubPrMutation, - type GitHubPrMutationOutcome -} from './github-pr-mutation-outcome' -import { - githubPrRepoSlugParam, - githubPrRequestParams, - type GitHubPrRepoSlug -} from './github-pr-repo-slug' -import type { MobileSessionRpcSender } from './mobile-session-rpc-sender' - -// The conversation half of the github.* PR mutation surface: review-thread replies, root comments, -// thread resolution and the slug-addressed comment edit/delete. Split from the PR action mutations -// because the two are driven by different hooks and this file was over the max-lines budget. - -// Reply within a review thread. Host returns GitHubCommentResult -// (`{ ok, comment } | { ok:false, error }`), which the status reader admits. -// We refetch afterward, so the returned comment is unused. -export function fetchAddPRReviewCommentReply( - client: MobileSessionRpcSender, - worktreeId: string, - args: { - prNumber: number - commentId: number - body: string - threadId?: string - path?: string - line?: number - prRepo?: GitHubPrRepoSlug | null - } -): Promise { - const params: Record = { - prNumber: args.prNumber, - commentId: args.commentId, - body: args.body - } - if (args.threadId) { - params.threadId = args.threadId - } - if (args.path) { - params.path = args.path - } - if (typeof args.line === 'number') { - params.line = args.line - } - return settleGithubPrMutation(githubPrReviewCommentReplyAdd, () => - githubPrReviewCommentReplyAdd.request( - client, - githubPrRequestParams(githubPrReviewCommentReplyAdd.operation.method, worktreeId, params, { - prRepo: args.prRepo - }) - ) - ) -} - -// Add a root conversation comment to the PR. Host returns GitHubCommentResult. -export function fetchAddIssueComment( - client: MobileSessionRpcSender, - worktreeId: string, - args: { prNumber: number; body: string; prRepo?: GitHubPrRepoSlug | null } -): Promise { - const params: Record = { - number: args.prNumber, - body: args.body, - type: 'pr' - } - return settleGithubPrMutation(githubPrIssueCommentAdd, () => - githubPrIssueCommentAdd.request( - client, - githubPrRequestParams(githubPrIssueCommentAdd.operation.method, worktreeId, params, { - prRepo: args.prRepo - }) - ) - ) -} - -// Resolve/unresolve a review thread. `resolve` picks the direction (the host runs -// the matching GraphQL mutation). Unlike the comment mutations, the host returns a -// bare boolean, so a falsy result is a failure rather than the "no status" success. -export function fetchResolveReviewThread( - client: MobileSessionRpcSender, - worktreeId: string, - args: { threadId: string; resolve: boolean; prRepo?: GitHubPrRepoSlug | null } -): Promise { - return settleGithubPrConfirmation( - githubPrReviewThreadResolve, - () => - githubPrReviewThreadResolve.request( - client, - githubPrRequestParams( - githubPrReviewThreadResolve.operation.method, - worktreeId, - { threadId: args.threadId, resolve: args.resolve }, - { prRepo: args.prRepo } - ) - ), - 'Failed to update review thread.' - ) -} - -// Edit a root conversation (issue) comment. The host RPC is slug-addressed -// (owner/repo/commentId), not worktree-addressed, so the params are passed -// directly rather than via the PR-scoped builder. Host returns the -// GitHubProjectMutationResult `{ ok }` envelope the status reader admits. -export function fetchUpdateIssueComment( - client: MobileSessionRpcSender, - args: { owner: string; repo: string; host?: string; commentId: number; body: string } -): Promise { - return settleGithubPrMutation(githubPrIssueCommentEdit, () => - githubPrIssueCommentEdit.request(client, { - ...githubPrRepoSlugParam(args), - commentId: args.commentId, - body: args.body - }) - ) -} - -// Delete a root conversation (issue) comment. Slug-addressed like the edit wrapper. -export function fetchDeleteIssueComment( - client: MobileSessionRpcSender, - args: { owner: string; repo: string; host?: string; commentId: number } -): Promise { - return settleGithubPrMutation(githubPrIssueCommentDelete, () => - githubPrIssueCommentDelete.request(client, { - ...githubPrRepoSlugParam(args), - commentId: args.commentId - }) - ) -} diff --git a/mobile/src/session/github-pr-mutations.ts b/mobile/src/session/github-pr-mutations.ts index 4d4598fd58f..9d5bc815b72 100644 --- a/mobile/src/session/github-pr-mutations.ts +++ b/mobile/src/session/github-pr-mutations.ts @@ -2,9 +2,14 @@ import type { GitHubPRMergeMethod } from '../../../src/shared/github/pull-reques import { githubPrAutoMergeSet, githubPrChecksRerun, + githubPrIssueCommentAdd, + githubPrIssueCommentDelete, + githubPrIssueCommentEdit, githubPrMergeRun, + githubPrReviewCommentReplyAdd, githubPrReviewersRemove, githubPrReviewersRequest, + githubPrReviewThreadResolve, githubPrStateSet, githubPrTitleSet } from './github-pr-mutation-operations' @@ -13,21 +18,19 @@ import { settleGithubPrMutation, type GitHubPrMutationOutcome } from './github-pr-mutation-outcome' -import { githubPrRequestParams, type GitHubPrRepoSlug } from './github-pr-repo-slug' +import { + githubPrRepoSlugParam, + githubPrRequestParams, + type GitHubPrRepoSlug +} from './github-pr-repo-slug' import type { MobileSessionRpcSender } from './mobile-session-rpc-sender' -// The PR action half of the github.* mutation surface: merge, auto-merge, open/close, reviewers, -// check reruns and the inline title edit. The conversation mutations live next door; both are -// re-exported here so consumers keep one entry point for the surface. +// The github.* PR mutation surface: merge, auto-merge, open/close, reviewers, check reruns, the +// inline title edit, and the conversation mutations (thread replies, root comments, resolution, +// slug-addressed comment edit/delete). Each wrapper builds params and hands the bound operation to +// the settle shape its host reply contract calls for. export type { GitHubPrMutationOutcome } from './github-pr-mutation-outcome' -export { - fetchAddIssueComment, - fetchAddPRReviewCommentReply, - fetchDeleteIssueComment, - fetchResolveReviewThread, - fetchUpdateIssueComment -} from './github-pr-comment-mutations' export function fetchMergePR( client: MobileSessionRpcSender, @@ -173,3 +176,118 @@ export function fetchRerunPRChecks( ) ) } + +// Reply within a review thread. Host returns GitHubCommentResult +// (`{ ok, comment } | { ok:false, error }`), which the status reader admits. +// We refetch afterward, so the returned comment is unused. +export function fetchAddPRReviewCommentReply( + client: MobileSessionRpcSender, + worktreeId: string, + args: { + prNumber: number + commentId: number + body: string + threadId?: string + path?: string + line?: number + prRepo?: GitHubPrRepoSlug | null + } +): Promise { + const params: Record = { + prNumber: args.prNumber, + commentId: args.commentId, + body: args.body + } + if (args.threadId) { + params.threadId = args.threadId + } + if (args.path) { + params.path = args.path + } + if (typeof args.line === 'number') { + params.line = args.line + } + return settleGithubPrMutation(githubPrReviewCommentReplyAdd, () => + githubPrReviewCommentReplyAdd.request( + client, + githubPrRequestParams(githubPrReviewCommentReplyAdd.operation.method, worktreeId, params, { + prRepo: args.prRepo + }) + ) + ) +} + +// Add a root conversation comment to the PR. Host returns GitHubCommentResult. +export function fetchAddIssueComment( + client: MobileSessionRpcSender, + worktreeId: string, + args: { prNumber: number; body: string; prRepo?: GitHubPrRepoSlug | null } +): Promise { + const params: Record = { + number: args.prNumber, + body: args.body, + type: 'pr' + } + return settleGithubPrMutation(githubPrIssueCommentAdd, () => + githubPrIssueCommentAdd.request( + client, + githubPrRequestParams(githubPrIssueCommentAdd.operation.method, worktreeId, params, { + prRepo: args.prRepo + }) + ) + ) +} + +// Resolve/unresolve a review thread. `resolve` picks the direction (the host runs +// the matching GraphQL mutation). Unlike the comment mutations, the host returns a +// bare boolean, so a falsy result is a failure rather than the "no status" success. +export function fetchResolveReviewThread( + client: MobileSessionRpcSender, + worktreeId: string, + args: { threadId: string; resolve: boolean; prRepo?: GitHubPrRepoSlug | null } +): Promise { + return settleGithubPrConfirmation( + githubPrReviewThreadResolve, + () => + githubPrReviewThreadResolve.request( + client, + githubPrRequestParams( + githubPrReviewThreadResolve.operation.method, + worktreeId, + { threadId: args.threadId, resolve: args.resolve }, + { prRepo: args.prRepo } + ) + ), + 'Failed to update review thread.' + ) +} + +// Edit a root conversation (issue) comment. The host RPC is slug-addressed +// (owner/repo/commentId), not worktree-addressed, so the params are passed +// directly rather than via the PR-scoped builder. Host returns the +// GitHubProjectMutationResult `{ ok }` envelope the status reader admits. +export function fetchUpdateIssueComment( + client: MobileSessionRpcSender, + args: { owner: string; repo: string; host?: string; commentId: number; body: string } +): Promise { + return settleGithubPrMutation(githubPrIssueCommentEdit, () => + githubPrIssueCommentEdit.request(client, { + ...githubPrRepoSlugParam(args), + commentId: args.commentId, + body: args.body + }) + ) +} + +// Delete a root conversation (issue) comment. Slug-addressed like the edit wrapper. +export function fetchDeleteIssueComment( + client: MobileSessionRpcSender, + args: { owner: string; repo: string; host?: string; commentId: number } +): Promise { + return settleGithubPrMutation(githubPrIssueCommentDelete, () => + githubPrIssueCommentDelete.request(client, { + ...githubPrRepoSlugParam(args), + commentId: args.commentId + }) + ) +}