Skip to content

feat(desktop): reply to PR review threads from the Changes pane - #7166

Merged
AviPeltz merged 2 commits into
mainfrom
add-comment-reply-changes
Sep 4, 2026
Merged

AviPeltz merged 2 commits into
mainfrom
add-comment-reply-changes

Conversation

@AviPeltz

@AviPeltz AviPeltz commented Sep 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • The workspace Changes pane can now reply to PR review threads and post them to GitHub, matching the PR view's Code tab. Each thread bubble gets a reply box (Cmd/Ctrl+Enter submits) and a Reply button beside Resolve.
  • New workspace-scoped git.replyToReviewThread mutation. The GitHub call it shares with pullRequests.replyToThread moves into one helper so the two surfaces can't drift.

Why / Context

Review threads already rendered inline in the Changes pane with resolve/unresolve, but answering one meant leaving for the PR view or GitHub. The PR view had the full reply flow, so this ports that implementation over rather than inventing a second one.

How It Works

  • git.getPullRequestThreads already returns each comment's REST databaseId; useDiffAnnotationsByPath now puts the first comment's id on the thread metadata as replyToCommentId.
  • DiffPane's CommentThread owns a git.replyToReviewThread mutation. On send it clears the draft; on success it invalidates the workspace threads query, and the annotation version hash already includes comment count, so the new comment renders on the next refetch. On failure it toasts and hands the draft back (unless a new one was started).
  • git.replyToReviewThread looks up workspace → linked PR row and posts via pulls.createReplyForReviewComment using the PR row's repo owner/name/number. A comment id from another PR 404s rather than landing somewhere unexpected.
  • replyToReviewComment (new, git/utils) wraps the octokit call plus actionRejectionError mapping; pullRequests.replyToThread is refactored onto it.

Manual QA Checklist

Not run against the live app: no dev app was running from this worktree, and posting a real reply to GitHub is outward-facing. Worth a pass before merge:

  • In a workspace linked to a PR with review comments, open the Changes pane: each thread shows the reply box under the comments
  • Type a reply and click Reply (or Cmd+Enter): it appears on GitHub and shows in the thread within the 30s poll or on window focus
  • Reply stays disabled while the draft is blank or a post is in flight
  • With network off or a revoked token: "Couldn't post reply" toast and the draft comes back
  • Resolve / Unresolve still work beside the new button
  • Resolved and outdated threads still start collapsed; expanding shows the reply box

Testing

  • bun run typecheck (host-service and desktop)
  • bun test src/trpc/router/git src/trpc/router/pull-requests in host-service (145 pass). New reply-to-review-thread.test.ts: happy path, blank body rejected before GitHub, no linked PR → NOT_FOUND, GitHub 404 → NOT_FOUND
  • bun test on the DiffPane tree in desktop (30 pass). New CommentThread.test.tsx: submit + clear + invalidate, Cmd+Enter, disabled states, in-flight guard, orphaned thread keeps its draft, failure restores the draft
  • bun run check:i18n clean. Every string the reply box uses already exists in all 17 locales from the PR view, so no catalog changes
  • bun test in packages/i18n (enforced-dirs, display-only) and biome check on the changed files

Design Decisions

  • PR row over resolveGithubRepo for the reply target: getCheckJobLogs already uses the PR row; it needs no remote parsing and names exactly the repo the comment ids came from.
  • Draft restore on failure: the PR view clears optimistically and can't restore because its reply is a prop callback. Here the component owns the mutation, so restoring is two lines. A small, deliberate divergence.

Follow-ups

  • The resolve/unresolve GraphQL mutation is still duplicated between git.setReviewThreadResolution and pullRequests.setThreadResolution. The same shared-helper treatment would fit; left out to keep this focused.

https://claude.ai/code/session_01DQF36hf8kmYHRggDxFwXuk


Summary by cubic

Adds reply support for PR review threads in the workspace Changes pane, matching the PR view's Code tab. You can now type a reply in each thread and submit it to GitHub; previously the pane only allowed resolving/unresolving threads.

New Features

  • Adds a reply box and Reply button to each thread bubble; Cmd/Ctrl+Enter also submits.
  • New workspace-scoped git.replyToReviewThread mutation posts the reply to the linked PR.
  • Failed replies toast an error and restore your draft.

Refactors

  • The reply box is now a shared ReviewThreadReplyComposer, used by the Changes pane and the PR view's Code tab.
  • The GitHub reply call and error mapping now live in a shared helper used by pullRequests.replyToThread and the new mutation.
  • Thread metadata now carries the first comment's database id so replies thread onto the correct comment.

Written for commit 36ff9a6. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added the ability to reply directly to review comment threads in the diff view.
    • Replies support trimmed text, Reply button, and Ctrl/Cmd+Enter submission.
    • Drafts are preserved when posting fails, with controls disabled for blank drafts or while submitting.
    • Reply controls are now consistent across diff and pull request review threads.
  • Bug Fixes

    • Review replies are correctly associated with the selected comment thread.
  • Tests

    • Added coverage for reply submission, validation, pending states, draft handling, and error scenarios.

The workspace Changes pane showed review threads with a resolve button but
no way to answer them; only the PR view's Code tab could post replies.
Bring the same flow over:

- git.replyToReviewThread: workspace-scoped mutation that posts through
  GitHub's reply-to-review-comment endpoint, resolving the repo and PR
  number from the workspace's linked PR row.
- The GitHub call and its error mapping move into a shared helper that
  pullRequests.replyToThread now uses too, so the two surfaces can't drift.
- DiffPane's CommentThread gets a reply textarea (Cmd/Ctrl+Enter submits)
  and a Reply button beside Resolve; the thread annotation metadata carries
  the first comment's databaseId to thread onto. A rejected reply hands the
  draft back instead of losing it.

All strings already exist in every locale from the PR view, so no catalog
changes.

Claude-Session: https://claude.ai/code/session_01DQF36hf8kmYHRggDxFwXuk
@coderabbitai

coderabbitai Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 2b3058e8-7bea-4b2a-8132-3888123e9449

📥 Commits

Reviewing files that changed from the base of the PR and between b924322 and 36ff9a6.

📒 Files selected for processing (6)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/ReviewThreadReplyComposer.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/components/PullRequestCommentThread/PullRequestCommentThread.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/components/CommentThread/CommentThread.test.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/components/CommentThread/CommentThread.tsx
  • packages/host-service/src/trpc/router/git/reply-to-review-thread.test.ts

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


📝 Walkthrough

Walkthrough

The change adds a shared reply composer, propagates review comment IDs through diff annotations, adds a protected tRPC reply mutation, and centralizes GitHub review-comment reply handling.

Changes

Review thread replies

Layer / File(s) Summary
Shared GitHub reply utility
packages/host-service/src/trpc/router/git/utils/reply-to-review-comment.ts, packages/host-service/src/trpc/router/pull-requests/procedures/reply-to-thread.ts
The shared utility posts replies and maps GitHub errors. The existing pull-request procedure delegates to it.
Protected reply mutation
packages/host-service/src/trpc/router/git/git.ts, packages/host-service/src/trpc/router/git/reply-to-review-thread.test.ts
The mutation validates input, resolves the linked pull request, submits the reply, and handles missing resources and GitHub errors.
Shared desktop reply composition
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/*, apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/$prNumber/components/PullRequestCommentThread/PullRequestCommentThread.tsx
The shared composer handles trimmed replies, keyboard submission, pending-state blocking, draft clearing, and error recovery. The pull-request thread uses it with its resolve action.
Diff thread reply wiring and tests
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/hooks/useDiffAnnotations/useDiffAnnotations.ts, apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/DiffPane.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/components/CommentThread/*
The diff annotation carries the first comment ID to CommentThread. The component submits replies through the new mutation, and tests cover success, validation, pending state, orphaned threads, and mutation failures.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to 36ff9

This adds GitHub review-thread replies in both desktop thread views while preserving drafts on failures and refreshing threads after successful replies. No concrete current-head merge-blocking risk remains.

Sequence Diagram(s)

sequenceDiagram
  participant DiffAnnotations
  participant DiffPane
  participant CommentThread
  participant replyToReviewThread
  participant replyToReviewComment
  participant GitHub
  DiffAnnotations->>DiffPane: provide replyToCommentId
  DiffPane->>CommentThread: render reply composer
  CommentThread->>replyToReviewThread: submit trimmed body
  replyToReviewThread->>replyToReviewComment: pass PR and comment data
  replyToReviewComment->>GitHub: create threaded review reply
  GitHub-->>replyToReviewComment: return created comment id
  replyToReviewThread-->>CommentThread: return mutation result
  CommentThread->>CommentThread: clear draft and refresh thread list
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 11 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the change, motivation, implementation, testing, design decisions, and manual QA status. It does not use the exact template headings, but it provides the required information …
Title check ✅ Passed The title uses conventional commit format and clearly identifies the primary change: replying to pull request review threads from the desktop Changes pane.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-comment-reply-changes

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.

@greptile-apps

greptile-apps Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds review-thread replies to the desktop workspace Changes pane and centralizes the GitHub reply operation shared with the pull-request Code tab. The UI derives a reply target from the first review comment, submits through a new workspace-scoped mutation, restores failed drafts, and refreshes thread annotations after success.

  • Adds the reply composer, keyboard submission, pending state, error recovery, and focused component tests.
  • Adds git.replyToReviewThread and tests its GitHub request and error mapping.
  • Extracts the existing Octokit reply call into a shared helper.
  • The new mutation needs workspace-level authorization before it is safe on shared hosts.

Confidence Score: 3/5

The PR is not safe to merge until the new mutation enforces workspace-level access before posting to GitHub.

Members of a shared host are authorized only at host granularity, and the new procedure accepts an arbitrary workspace ID without checking ownership, allowing an unauthorized reply to another user's linked pull request.

Files Needing Attention: packages/host-service/src/trpc/router/git/git.ts

Security Review

The workspace-scoped reply mutation trusts a caller-supplied workspace ID after only host-level authentication. On a shared host, a member can use another user's workspace and review-comment identifiers to post an unauthorized GitHub reply through the host's configured client.

Important Files Changed

Filename Overview
packages/host-service/src/trpc/router/git/git.ts Adds the workspace-scoped reply mutation, but its ID-only workspace lookup permits cross-workspace replies from members of a shared host.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/components/CommentThread/CommentThread.tsx Adds a reply composer with keyboard submission, pending-state handling, query invalidation, and failed-draft restoration.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/DiffPane/hooks/useDiffAnnotations/useDiffAnnotations.ts Propagates the first review comment's REST database ID as the thread reply target.
packages/host-service/src/trpc/router/git/utils/reply-to-review-comment.ts Extracts the Octokit review-reply operation and existing error mapping into a behaviorally compatible shared helper.
packages/host-service/src/trpc/router/pull-requests/procedures/reply-to-thread.ts Refactors the existing pull-request reply procedure onto the shared helper without changing its request or response contract.

Sequence Diagram

sequenceDiagram
  participant User as Shared-host member
  participant Relay
  participant Host as Host-service tRPC
  participant DB as Local workspace DB
  participant GitHub

  User->>Relay: git.replyToReviewThread(workspaceId, commentId, body)
  Relay->>Relay: Check organization and host membership
  Relay->>Host: Forward unchanged tRPC input
  Host->>DB: Find workspace by supplied ID
  DB-->>Host: Linked pull-request row
  Note over Host: Missing caller-to-workspace authorization
  Host->>GitHub: createReplyForReviewComment(...)
  GitHub-->>Host: New review comment
Loading
Prompt To Fix All With AI
### Issue 1
packages/host-service/src/trpc/router/git/git.ts:1069-1071
**Missing Workspace Authorization**

An authenticated member of a shared host can query another user's workspace threads and submit that workspace ID and one of its comment IDs here. Relay authorization checks host membership, but this lookup does not compare `workspace.createdByUserId` with `ctx.userId`. The mutation can therefore use the host's GitHub client to post a reply on another user's linked pull request. Enforce workspace-level access before resolving the pull request or posting the reply.

**How this was verified:** The relay forwards arbitrary tRPC input after checking only organization and host membership, and this procedure resolves the supplied workspace ID without a user-level authorization check before posting the reply.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(desktop): reply to PR review thread..." | Re-trigger Greptile

Comment on lines +1069 to +1071
}),
)
.mutation(async ({ ctx, input }) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Missing Workspace Authorization

An authenticated member of a shared host can query another user's workspace threads and submit that workspace ID and one of its comment IDs here. Relay authorization checks host membership, but this lookup does not compare workspace.createdByUserId with ctx.userId. The mutation can therefore use the host's GitHub client to post a reply on another user's linked pull request. Enforce workspace-level access before resolving the pull request or posting the reply.

How this was verified: The relay forwards arbitrary tRPC input after checking only organization and host membership, and this procedure resolves the supplied workspace ID without a user-level authorization check before posting the reply.

Knowledge Base Used: Host service API and transport

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/host-service/src/trpc/router/git/git.ts
Line: 1069-1071

Comment:
**Missing Workspace Authorization**

An authenticated member of a shared host can query another user's workspace threads and submit that workspace ID and one of its comment IDs here. Relay authorization checks host membership, but this lookup does not compare `workspace.createdByUserId` with `ctx.userId`. The mutation can therefore use the host's GitHub client to post a reply on another user's linked pull request. Enforce workspace-level access before resolving the pull request or posting the reply.

**How this was verified:** The relay forwards arbitrary tRPC input after checking only organization and host membership, and this procedure resolves the supplied workspace ID without a user-level authorization check before posting the reply.

**Knowledge Base Used:** [Host service API and transport](https://app.greptile.com/personal-org-6810/-/custom-context/knowledge-base/superset-sh/superset/-/docs/host-service-api-and-transport.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/host-service/src/trpc/router/git/git.ts">

<violation number="1" location="packages/host-service/src/trpc/router/git/git.ts:1072">
P0: Authorize `input.workspaceId` against `ctx.userId` before resolving its pull request. As written, any authenticated host member can supply another user's workspace ID and post a review reply through that workspace's linked pull request.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant UI as Changes Pane (DiffPane)
    participant CT as CommentThread Component
    participant TRPC as tRPC Router (Desktop Client)
    participant HS as Host Service (gitRouter)
    participant DB as Database
    participant GH as GitHub API
    
    Note over UI,GH: Reply to PR Review Thread from Changes Pane
    
    UI->>UI: useDiffAnnotationsByPath()
    UI->>UI: Extract first comment databaseId as replyToCommentId
    UI->>CT: Pass replyToCommentId + workspaceId
    
    CT->>CT: Initialize reply draft state
    
    User->>CT: Type reply text
    User->>CT: Click Reply button or Cmd/Ctrl+Enter
    
    alt Blank or whitespace draft
        CT-->>CT: Disable Reply button
    else Draft has content and not in-flight
        CT->>TRPC: git.replyToReviewThread.mutate({workspaceId, commentId, body})
        CT->>CT: Clear draft textarea
    end
    
    alt replyToCommentId is undefined (orphaned thread)
        CT->>CT: Show error toast "Couldn't send reply"
        CT->>CT: Keep draft text
    end
    
    TRPC->>HS: tRPC mutation request
    HS->>HS: Validate input (zod: workspaceId, commentId positive int, body trimmed min 1)
    
    HS->>DB: Look up workspace by id
    alt Workspace not found or no pullRequestId
        DB-->>HS: null / no PR
        HS-->>TRPC: NOT_FOUND error
        TRPC-->>CT: Error response
        CT->>CT: Restore draft + error toast "Couldn't post reply"
    else Workspace has pullRequestId
        DB-->>HS: Workspace row
        
        HS->>DB: Look up pull request by id
        alt PR row not found
            DB-->>HS: null
            HS-->>TRPC: INTERNAL_SERVER_ERROR
            TRPC-->>CT: Error response
            CT->>CT: Restore draft + error toast
        else PR row found
            DB-->>HS: PR row (repoOwner, repoName, prNumber)
            
            HS->>HS: Call replyToReviewComment helper
            HS->>GH: POST pulls.createReplyForReviewComment({owner, repo, pull_number, comment_id, body})
            
            alt GitHub accepts reply
                GH-->>HS: New comment data
                HS-->>TRPC: {id: newCommentId}
                TRPC-->>CT: Success
                CT->>CT: Invalidate getPullRequestThreads query
                CT-->>CT: New comment renders on next refetch
            else GitHub rejects (404, 403, etc.)
                GH-->>HS: Error with status
                HS->>HS: actionRejectionError mapping
                HS-->>TRPC: NOT_FOUND / other mapped code
                TRPC-->>CT: Error response
                CT->>CT: Restore draft (if textarea empty) + toast
            end
        end
    end
    
    Note over CT,HS: Resolution flow still works alongside reply
    CT->>TRPC: git.setReviewThreadResolution.mutate()
    TRPC->>HS: tRPC mutation request
    HS->>GH: Resolve/unresolve thread via GraphQL
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

}),
)
.mutation(async ({ ctx, input }) => {
const workspace = ctx.db.query.workspaces

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P0: Authorize input.workspaceId against ctx.userId before resolving its pull request. As written, any authenticated host member can supply another user's workspace ID and post a review reply through that workspace's linked pull request.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/host-service/src/trpc/router/git/git.ts, line 1072:

<comment>Authorize `input.workspaceId` against `ctx.userId` before resolving its pull request. As written, any authenticated host member can supply another user's workspace ID and post a review reply through that workspace's linked pull request.</comment>

<file context>
@@ -1053,4 +1054,51 @@ export const gitRouter = router({
+			}),
+		)
+		.mutation(async ({ ctx, input }) => {
+			const workspace = ctx.db.query.workspaces
+				.findFirst({ where: eq(workspaces.id, input.workspaceId) })
+				.sync();
</file context>

… test suite

Review follow-ups on #7166:

- CommentThread.test.tsx crashed the desktop suite on CI with "Unhandled
  error between tests". Two earlier suites replace `react` with a hooks-only
  stub for the rest of the process, and this test was the first afterwards
  to load react-syntax-highlighter (through CommentMarkdown), whose CommonJS
  build extends React.PureComponent at load time. Mock CommentMarkdown: the
  bodies are irrelevant to the reply flow.
- Extract ReviewThreadReplyComposer (textarea, Cmd/Ctrl+Enter, Reply button,
  no-target toast) and use it from both the Changes pane's CommentThread and
  the PR view's PullRequestCommentThread, so the two stop drifting. Each
  caller keeps its own dispatch and draft state.
- Cover the "workspace points at a pull request row that no longer exists"
  path in the replyToReviewThread test.

Claude-Session: https://claude.ai/code/session_01DQF36hf8kmYHRggDxFwXuk

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/ReviewThreadReplyComposer.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/ReviewThreadReplyComposer.tsx:64">
P3: The reply textarea has no accessible name because its placeholder is the only identifying text. Add a localized `aria-label` (or an associated label) so screen-reader users can distinguish the reply control.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


return (
<div className={cn("flex flex-col gap-2 border-t py-2", className)}>
<Textarea

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The reply textarea has no accessible name because its placeholder is the only identifying text. Add a localized aria-label (or an associated label) so screen-reader users can distinguish the reply control.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/ReviewThreadReplyComposer/ReviewThreadReplyComposer.tsx, line 64:

<comment>The reply textarea has no accessible name because its placeholder is the only identifying text. Add a localized `aria-label` (or an associated label) so screen-reader users can distinguish the reply control.</comment>

<file context>
@@ -0,0 +1,93 @@
+
+	return (
+		<div className={cn("flex flex-col gap-2 border-t py-2", className)}>
+			<Textarea
+				value={value}
+				onChange={(e) => onChange(e.target.value)}
</file context>

This branch was previously deployed

1 inactive deployment
preview — 36ff9a65 Deployed Sep 4, 2026 by AviPeltz via Deploy Web #9159
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