Skip to content

feat(issue-pane): show the workspace's linked issue in the right sidebar - #45

Merged
nplez1 merged 3 commits into
nplez1/mainfrom
nplez1/Issue-Pane
Oct 1, 2026
Merged

nplez1 merged 3 commits into
nplez1/mainfrom
nplez1/Issue-Pane

Conversation

@nplez1

@nplez1 nplez1 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner
Files Added Deleted Net
Test 11 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1102 $\color{#cf222e}{\Huge{\mathbf{−}}}$​10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​1092
Prod 32 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​3079 $\color{#cf222e}{\Huge{\mathbf{−}}}$​391 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​2688

ELI5

Orca can already remember which issue (Jira, Linear, or GitHub) a workspace was created from. This PR adds a place to actually see that issue: a new "Issue" tab in the right-hand panel that appears only when the current workspace is linked to one.

What Changed

Before: the linked issue was only a small badge on the workspace card. There was nowhere in the app to read it without switching to the Tasks view and finding it again.

After: when the active workspace has a linked issue, an Issue tab shows in the right sidebar. It contains:

  • The issue identifier, title (editable in place), and an Open in Jira / GitHub / Linear button.
  • Compact property rows for status, assignee, priority, and labels — each opens a small picker.
  • The issue description.

The assignee row is a typeahead:

  • Empty: a short list of people from the issue's board/project roster, with you pinned at the top.
  • Typing: for Jira, searches the whole Jira site; for Linear and GitHub, filters the team/repo roster.

Mechanism

  • New tab 'issue' in the RightSidebarTab union and its normalizers (store route, persistence, RPC params schema, activity-bar visibility).
  • The tab is data-dependent: a new linkedIssueOnly visibility flag hides it unless the active workspace has a supported linked issue. GitLab links are excluded because there is no issue-detail fetch path for them.
  • resolveWorkspaceLinkedIssue normalizes the persisted link (GitHub slot → Linear slot → legacy GitLab slot → created-from work item) so the pane and the meta editor agree on which issue a workspace owns.
  • Three provider panes (GithubLinkedIssuePane, LinearLinkedIssuePane, JiraLinkedIssuePane) render the compact rows. They reuse the Task view's own hooks and mutation wiring — useLinearIssueEditController, GHEditSection's handlers, and the Jira hydration hook — so edits invalidate the same caches and the two surfaces never drift.
  • Shared extractions so nothing is duplicated: gh-edit-section-pills, jira-issue-title-labels-editor, and the Jira hydration split into useJiraIssueWorkspaceDetail / useJiraIssueComments / useJiraIssueSideData.

Why

The workspace→issue link already existed and is set when you create a workspace from a task. Surfacing it in the sidebar means you can read (and lightly edit) the issue without leaving your workspace context.

Why this shape over the alternatives:

  • Not embedding the existing Task-view detail panes. LinearIssueWorkspace is a wide two-column page and JiraIssueWorkspace is a right-edge Sheet; neither reflows to a ~280px sidebar. So the pane composes the same edit controllers and handlers but with a layout built for the compressed width.
  • Not a provider-neutral uniform schema. GitHub has no priority and no single assignee; Jira and Linear do. Each provider keeps its own capability set.
  • Keeping the edits routed through existing store/runtime actions so the Task view and the pane stay consistent rather than each maintaining its own cache writes.

Known limitation

Adding 'issue' to STATIC_RIGHT_SIDEBAR_TABS is a wire change. A newer paired client sending rightSidebarTab: 'issue' to an older host has that small ui.set patch rejected, so the active-tab preference does not persist across that version skew (no crash, no data loss, local state keeps working). This follows the existing static-tab precedent (pr-checks). Closing it fully needs a host-capability gate, which is deliberately out of scope here.

Linked Issue

N/A — fork-internal change (no upstream issue).

Visual Proof

UI change. Screenshots/video were not captured in this environment and still need to be attached by the author (before/after of the right sidebar with and without the Issue tab, plus an open assignee typeahead).

Testing

Automated:

  • pnpm tc — typecheck (node + renderer) passes.
  • pnpm run check:code-quality:changed — changed-lines quality gate (lint, type-aware, react-doctor, design system) passes.
  • Localization extraction / catalogs / coverage gates pass.
  • ~2.66k affected tests pass (right-sidebar, github-item-dialog, task-page, linear-item-drawer, jira workspace), including new tests for the linked-issue resolver, tab visibility, pane dispatch, the typeahead (self-pinning, client filter, directory search, secondary-identity match, stale-result clearing), and the compact row renderers.

Manual: the app was not launched for a visual check in this environment, and there is no SSH/mobile smoke test. Reviewer steps: open a workspace linked to a Jira/Linear/GitHub issue, open the right sidebar, and confirm the Issue tab appears with the rows and typeahead.

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

AI Disclosure

Implemented with an AI coding agent (pi) under author review; a stronger reviewer model critiqued the design and the lifecycle edges. No upstream skill-installer source, tests, fixtures, or registry entries were copied.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: no new IPC surface is reachable from untrusted content; mutations reuse existing credential-scoped provider clients.
  • Cross-platform: no new shortcut or path handling; the assignee combobox and popovers are platform-neutral. Only exercised on macOS.
  • Remote SSH: the pane uses the same runtime clients and sourceContext as the Task view, so hosted workspaces route through the same path. Not manually validated over SSH.
  • Mobile: no mobile surface changed; the tab list schema is shared, see the wire limitation above.
  • Performance: list fetches are per-provider and cached through the existing stores; the typeahead search is debounced (250 ms) and cleared on query change.
  • config/scripts/check-changed-code-quality.mjs gained two entries in its react-doctor suppression map (the pane's async fetch effects), per the repo's documented mechanism for accepting those findings.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • Before/after screenshots or videos attached for UI changes (pending — see Visual Proof)
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered
  • pnpm lint, pnpm typecheck, pnpm test pass (build not run)

@nplez1
nplez1 force-pushed the nplez1/Issue-Pane branch from e70e6db to 1874d78 Compare October 1, 2026 05:48
nplez1 added 3 commits October 1, 2026 00:10
Add an Issue tab to the right-side panel that appears only while the active
workspace is linked to a GitHub, Linear, or Jira issue. The pane renders the
issue as compact vertical property rows — status, assignee, priority, labels —
with an inline-editable title, a description, and an "Open in <provider>"
button, so it fits the ~280px sidebar instead of reusing the Task view's wide
controls.

The assignee field is a typeahead: an empty query lists a short roster with the
current user pinned first, and typing searches the wider directory for Jira or
filters the roster for Linear and GitHub.

Also extracts shared pieces so the Task view and the pane stay in sync:
gh-edit-section-pills, jira-issue-title-labels-editor, and two Jira hydration
hooks (useJiraIssueWorkspaceDetail, useJiraIssueComments, useJiraIssueSideData).

Known limitation: adding 'issue' to STATIC_RIGHT_SIDEBAR_TABS means a newer
paired client sending that tab to an older host has the small ui.set patch
rejected, so the tab preference does not persist across that skew. Follows the
existing static-tab precedent; a host-capability gate would close it fully.
Add a compact comment thread and a composer to each provider pane, so an
issue's conversation can be read and replied to without leaving the sidebar.

- Shared IssueCommentThread: avatar, author, relative time, markdown body.
- Jira reuses the Task view's JiraIssueCommentComposer, Linear reuses
  LinearIssueCommentFooter, GitHub reuses GHCommentComposer.
- Each posts through the existing mutation path and appends optimistically, so
  a reply appears immediately and the Task view stays in sync.
React Doctor flags a render-time ref write in IssueAssigneeCombobox
("Ref mutated during render"): React may replay or discard render work, so
the write can leak from UI that never commits. Move the latest-callback ref
sync into an effect. Behavior is unchanged — useRef already seeds the value.
@nplez1
nplez1 force-pushed the nplez1/Issue-Pane branch from ab01ec3 to 1511a76 Compare October 1, 2026 07:11
@nplez1
nplez1 merged commit 0df861c into nplez1/main Oct 1, 2026
40 checks passed
nplez1 added a commit that referenced this pull request Oct 1, 2026
…bar (#45)

* feat(issue-pane): show the workspace's linked issue in the right sidebar

Add an Issue tab to the right-side panel that appears only while the active
workspace is linked to a GitHub, Linear, or Jira issue. The pane renders the
issue as compact vertical property rows — status, assignee, priority, labels —
with an inline-editable title, a description, and an "Open in <provider>"
button, so it fits the ~280px sidebar instead of reusing the Task view's wide
controls.

The assignee field is a typeahead: an empty query lists a short roster with the
current user pinned first, and typing searches the wider directory for Jira or
filters the roster for Linear and GitHub.

Also extracts shared pieces so the Task view and the pane stay in sync:
gh-edit-section-pills, jira-issue-title-labels-editor, and two Jira hydration
hooks (useJiraIssueWorkspaceDetail, useJiraIssueComments, useJiraIssueSideData).

Known limitation: adding 'issue' to STATIC_RIGHT_SIDEBAR_TABS means a newer
paired client sending that tab to an older host has the small ui.set patch
rejected, so the tab preference does not persist across that skew. Follows the
existing static-tab precedent; a host-capability gate would close it fully.

* feat(issue-pane): show and post comments from the Issue pane

Add a compact comment thread and a composer to each provider pane, so an
issue's conversation can be read and replied to without leaving the sidebar.

- Shared IssueCommentThread: avatar, author, relative time, markdown body.
- Jira reuses the Task view's JiraIssueCommentComposer, Linear reuses
  LinearIssueCommentFooter, GitHub reuses GHCommentComposer.
- Each posts through the existing mutation path and appends optimistically, so
  a reply appears immediately and the Task view stays in sync.

* fix(issue-pane): stop mutating the search ref during render

React Doctor flags a render-time ref write in IssueAssigneeCombobox
("Ref mutated during render"): React may replay or discard render work, so
the write can leak from UI that never commits. Move the latest-callback ref
sync into an effect. Behavior is unchanged — useRef already seeds the value.
nplez1 added a commit that referenced this pull request Oct 6, 2026
…bar (#45)

* feat(issue-pane): show the workspace's linked issue in the right sidebar

Add an Issue tab to the right-side panel that appears only while the active
workspace is linked to a GitHub, Linear, or Jira issue. The pane renders the
issue as compact vertical property rows — status, assignee, priority, labels —
with an inline-editable title, a description, and an "Open in <provider>"
button, so it fits the ~280px sidebar instead of reusing the Task view's wide
controls.

The assignee field is a typeahead: an empty query lists a short roster with the
current user pinned first, and typing searches the wider directory for Jira or
filters the roster for Linear and GitHub.

Also extracts shared pieces so the Task view and the pane stay in sync:
gh-edit-section-pills, jira-issue-title-labels-editor, and two Jira hydration
hooks (useJiraIssueWorkspaceDetail, useJiraIssueComments, useJiraIssueSideData).

Known limitation: adding 'issue' to STATIC_RIGHT_SIDEBAR_TABS means a newer
paired client sending that tab to an older host has the small ui.set patch
rejected, so the tab preference does not persist across that skew. Follows the
existing static-tab precedent; a host-capability gate would close it fully.

* feat(issue-pane): show and post comments from the Issue pane

Add a compact comment thread and a composer to each provider pane, so an
issue's conversation can be read and replied to without leaving the sidebar.

- Shared IssueCommentThread: avatar, author, relative time, markdown body.
- Jira reuses the Task view's JiraIssueCommentComposer, Linear reuses
  LinearIssueCommentFooter, GitHub reuses GHCommentComposer.
- Each posts through the existing mutation path and appends optimistically, so
  a reply appears immediately and the Task view stays in sync.

* fix(issue-pane): stop mutating the search ref during render

React Doctor flags a render-time ref write in IssueAssigneeCombobox
("Ref mutated during render"): React may replay or discard render work, so
the write can leak from UI that never commits. Move the latest-callback ref
sync into an effect. Behavior is unchanged — useRef already seeds the value.
nplez1 pushed a commit that referenced this pull request Oct 19, 2026
…iew off the deprecated owner resolver (stablyai#30562)

* refactor(renderer): fold browser creation, file actions and doc-preview callers off the deprecated owner resolver

The creation-action policy and browser creation (#3, #48) fold together, so the provider the
policy offers is the one creation uses. Browser panes, page lifecycle and conversion, tab
duplication, the explorer tree pane, doc-preview actions and editor path moves (#21, #43, #45-#47,
#49, #50) read runtimeEnvironmentIdWithLegacyFallbackUnlessTwin. File-explorer writes on a folder
(#51) take the owner from the rows alone, never from the focused server. Deprecated importers
16 -> 6.

* refactor(renderer): fold file preview off the deprecated owner resolver; Open in Orca Browser refuses a twin

A project two hosts publish reads as no server for the doc-preview plan, but the file:// path now
refuses it with its own message instead of opening this machine's copy (#7). Deprecated importers
6 -> 5.

* fix(renderer): a twin's file preview and open-externally refuse instead of opening this machine's copy

Codex P2 on the F7 folds: a folder twin read as no server, so the preview plan built a local
file:// tab and open-externally handed the path to this machine's OS. Both now check the owner
for ambiguity first. Also fix two test fixtures that broke the renderer typecheck.

* refactor(renderer): move the file:// open target out of file-preview.ts

file-preview.ts crossed its line limit after main grew it; the file:// target, its type and its two
refusal messages move to workspace-file-browser-open-target.ts, which they never depended on
file-preview for.

* test: mock the replacement resolver in the quick-action availability suite (Codex P2)
@nplez1
nplez1 deleted the nplez1/Issue-Pane branch October 24, 2026 03:23
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