refactor(mobile): undo the github-pr-mutations split, which max-lines no longer forces

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
This commit is contained in:
Jinwoo-H
2026-09-14 14:58:58 -04:00
parent cda6c002a1
commit 6fb2aaa19f
2 changed files with 129 additions and 148 deletions
@@ -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<GitHubPrMutationOutcome> {
const params: Record<string, unknown> = {
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<GitHubPrMutationOutcome> {
const params: Record<string, unknown> = {
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<GitHubPrMutationOutcome> {
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<GitHubPrMutationOutcome> {
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<GitHubPrMutationOutcome> {
return settleGithubPrMutation(githubPrIssueCommentDelete, () =>
githubPrIssueCommentDelete.request(client, {
...githubPrRepoSlugParam(args),
commentId: args.commentId
})
)
}
+129 -11
View File
@@ -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<GitHubPrMutationOutcome> {
const params: Record<string, unknown> = {
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<GitHubPrMutationOutcome> {
const params: Record<string, unknown> = {
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<GitHubPrMutationOutcome> {
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<GitHubPrMutationOutcome> {
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<GitHubPrMutationOutcome> {
return settleGithubPrMutation(githubPrIssueCommentDelete, () =>
githubPrIssueCommentDelete.request(client, {
...githubPrRepoSlugParam(args),
commentId: args.commentId
})
)
}