8.7 KiB
created, status, requirements, system_design, legacy_specs
| created | status | requirements | system_design | legacy_specs | ||
|---|---|---|---|---|---|---|
| 2026-08-26 | complete |
|
|
Implementation Plan: PR Task Status Hover Hydration
Overview
Make every GitHub task PR indicator disclose details consistently. First add a task-scoped hydration path for compact indicators. Then add the author identity to the shared summary and the existing mobile drawer.
This order makes the data available before the presentation and end-to-end work depends on it.
Scope
In scope
- Open a tooltip for compact GitHub PR indicators on mouse hover and keyboard focus.
- Load persisted full PR records for only the disclosed task.
- Deduplicate concurrent loads, reuse store data, guard HTTP and WebSocket races, and permit retry after an error.
- Preserve workspace ownership for live TaskPR updates. The browser must reject missing or foreign workspace IDs, and typed backend events must route by their owning workspace without falling back to a global broadcast.
- Show the GitHub author login in the task summary.
- Show the same author login in the existing coarse-pointer PR-status drawer.
- Add focused component, desktop Playwright, and mobile Playwright coverage.
Out of scope
- Upstream GitHub refreshes from the task-row indicator.
- Workspace-wide PR loading for the sidebar.
- Changes to task-summary persistence or projection fields.
- New task-row touch targets, drawers, navigation, or provider associations.
- Author support for GitLab or registered provider summaries.
Technical approach
Task-scoped disclosure hydration
Add a hook under hooks/domains/github that uses listTaskPRs([taskId]) when
taskPRs.byTaskId[taskId] is empty for the active workspace context. Scope the
in-flight registry to the Zustand store and key it by workspace, workspace
context generation, and task. Preserve deletion tombstones so a late response
cannot restore an association removed while it was pending.
Update PRTaskIcon and TaskContributionIcons so compact and full data use one
tooltip trigger. Compact content shows localized loading or unavailable text.
Successful data updates replace the content without unmounting the trigger or
closing the tooltip.
Before response application, compare the active workspace and current store records. Preserve matching records that arrived from WebSocket events. Add only missing PR identities from the HTTP result.
Workspace-scoped live PR updates
Treat TaskPR.workspace_id as the authoritative owner of a live update. The
frontend handler applies an update only when that ID is present and matches the
active workspace, preserving the current scoped cache for missing or foreign
payloads. The backend exposes TaskPR.WorkspaceID to the notification
broadcaster and routes typed PR updates and detachments through the fail-closed
workspace path when authentication is enforced, so an unattributed event is
dropped instead of broadcast globally.
Author presentation
Add optional author data to ChangeRequestTaskStatusSummaryData. Derive the
value from TaskPR.author_login and show localized task:byAuthor copy below
the title.
Extend ChangeRequestPopoverHeader with an optional author value. Pass the
GitHub author from PRCIPopover so desktop status content and the existing
mobile drawer use the same text.
Localization
Add localized loading and unavailable copy to the GitHub namespace in English,
Portuguese, Simplified Chinese, Hong Kong Chinese, and Taiwan Chinese. Reuse
the existing localized task:byAuthor key for author presentation.
Tests
| Acceptance criteria | Evidence |
|---|---|
AC-UI-PR-TASK-STATUS-SUMMARY-001.13 to .16 |
A new hydration-hook test covers task scope, one in-flight request, cache reuse, workspace and task-context changes, deletion during an HTTP request, empty/error retry, and HTTP/WS ordering. Render tests cover mouse and keyboard disclosure states, including focus continuity. |
AC-UI-PR-TASK-STATUS-SUMMARY-001.17 |
Summary derivation and shared render tests cover a present and missing author login. |
Existing .1 to .12 |
Existing PR icon and shared summary suites remain green. |
AC-UI-PR-TASK-STATUS-SUMMARY-001.18 |
Existing status-chip component tests and mobile Playwright coverage prove drawer author visibility and unchanged task-row navigation. |
AC-UI-PR-TASK-STATUS-SUMMARY-001.19 |
github.test.ts proves missing and foreign live updates leave the active scoped cache unchanged; task_notifications_test.go proves typed events reach only the owning workspace and unattributed events are dropped when auth is enforced; the singleton panel test preserves taskPR scope metadata during task switching. |
E2E tests
apps/web/e2e/tests/pr/pr-sidebar-hover-hydration.spec.tsuses thechromiumproject. It opens an unrelated task, hovers an inactive task PR indicator, observes the task-scoped request, and checks the author and structured rows.apps/web/e2e/tests/task/mobile-task-status-summary.spec.tsuses themobile-chromeproject. It taps the row, opens the current PR-status drawer, checks the author, and checks for horizontal overflow.
Mobile design contract
- Desktop outcome: Hover or keyboard focus opens and hydrates the PR task summary.
- Mobile entry: The task row remains the entry point. The user opens the task and then uses the existing PR-status chip.
- Exemplars:
session-task-switcher-sheet.tsxowns task navigation.pr-status-chip.tsxowns the coarse-pointer drawer. - Hierarchy: The task row stays primary. The PR author is secondary content below the title in the existing drawer.
- Presentation: Reuse the inset PR-status drawer. Do not add another drawer or a compact icon hit target.
- Scroll and geometry: Keep the drawer's existing internal scroll owner, safe-area behavior, and viewport containment.
- Shared state: Desktop and mobile read the same
TaskPR.author_login. - Proof: The mobile Playwright scenario checks navigation, drawer content, and horizontal containment.
Work orders
Task 02 depends on Task 01. The work orders are sequential and do not authorize subagents.
Verification results
- Focused web unit suite: 163 tests passed across 10 files after the review fixup, including the workspace-context generation regression test.
- Web typecheck passed.
- Web i18n check and ratchet passed.
- Full web lint passed.
- Desktop Playwright hydration scenario passed, including task-scoped request deduplication, structured details, author identity, and cache reuse.
- Mobile Chrome Playwright scenario passed, including task navigation, the existing PR drawer, author identity, and horizontal containment.
- Web E2E build passed.
- Fresh desktop and mobile captures were generated, inspected, compressed,
and validated through
apps/web/.pr-assets/manifest.json. - The repository-wide E2E sleep-policy lint remains baseline-red with 188 unrelated errors. Both changed E2E files pass the same lint directly.
- PR review fixup coverage also verifies task-id and workspace-context races, deletion tombstones, and keyboard focus continuity during hydration.
- Workspace-routing review fixup on 2026-08-26 added the
workspace_idfrontend contract, missing/foreign event guards, typed backend workspace extraction, and fail-closed notification tests. The focused frontend suite passed 95 tests across 6 files and the backend gateway/GitHub suites passed 2,176 tests. The full frontend Vitest run was stopped after the requested 15-minute local window without a failure result or terminal summary; the PR checks remain the authoritative broad-suite validation.
Documentation impact
No public documentation change is required. This package updates the durable UI requirement and adds its system design.
Risks
- A late HTTP result can replace newer WebSocket data unless current store identities win during response application.
- One hook instance per row can produce duplicate requests unless the in-flight registry is scoped above each component.
- A request that starts on pointer entry can finish after pointer leave. The result must remain cached without reopening the tooltip.
- Radix can keep hidden tooltip portals mounted. E2E locators must target the active tooltip content.
- Adding author text can increase summary height and can wrap in translated layouts. Desktop and mobile tests must retain viewport containment.
- A missing or mismatched workspace ID must never be replaced with the active workspace or reach a global notification broadcast.