WIP: Pilot safe OpenCode pull request reviews #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue/109-opencode-review-bot-pilot"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Testing
/oc review
OpenCode Review
Execution completed for
lambadalambda/pleromanetat1a043729493a(job #6).Findings
Medium
Unbounded growth of status-engagement tracking maps —
src/routes/app/[...path]/+page.svelteThe new revision-tracking structures (
statusEngagementSnapshots,statusEngagementNotificationRevisions,statusEngagementNotificationArrivals,notificationEngagementSignatures,seenNotificationEngagementSignatures) are keyed by status/notification IDs and never pruned.invalidateStatusActionRequestsresets them only on session/route invalidation, so a long-running session that views many posts will accumulate entries indefinitely. Consider evicting entries for status IDs no longer present in any loaded surface, or limiting to the most-recent N targets. This is the most concrete memory-growth concern introduced by the count-reconciliation feature.Floating image preview is repositioned on every scroll/resize without throttling —
src/lib/rebuild/CompactMediaPreview.sveltepositionFullPhotois bound towindow.scroll(capture),window.resize,visualViewport.resize, andvisualViewport.scroll, plus imageonload. Each invocation performsgetBoundingClientRect()reads, multipleawait tick()calls, and updatesfullPhotoStyle. There is no throttle, debounce, orrequestAnimationFramecoalescing. On lower-end devices and long hover sessions this can introduce jank, especially because the effect tears down and re-creates listeners on everyfullPhoto/fullPhotoAnchorchange. Consider anrAF-batched reposition and keeping listeners attached for the lifetime of the open preview (they are already gated by the open state).Low
Misleading time-bucket labels in NotificationsPage —
src/lib/rebuild/NotificationsPage.sveltebucketFormaps ages 1–6 h to "Today", 6–48 h to "Yesterday", and 2–7 days to "This week". The labels do not match the implied semantics and will be confusing for users (e.g., a 7-hour-old notification shows under "Yesterday"). Either rename the buckets (e.g., "Recent", "Today", "Earlier this week") or compute them against calendar days.Redundant condition in WebSocket onerror handler —
src/lib/pleroma/streaming.tsThe inner
if (!closed)is unreachable becauseclosedcannot change synchronously between the two checks. Collapse to a singleonError?.(event);after the early return.role="note"is non-standard —src/lib/rebuild/CompactMediaPreview.sveltenoteis not in the WAI-ARIA 1.2 vocabulary; some screen readers will ignore it. Use a standard role such asstatus, or omitroleand rely on the visible text.Notification actionable row loses pointer affordance —
src/app.css,src/lib/rebuild/NotifRow.svelteThe old rule
.notif-row.actionable { cursor: pointer; }was removed and the actionable surface is now a real<button class="notif-row-text">. Browser default cursor for<button>isdefault, so the row no longer signals clickability. Addcursor: pointerto.notif-row-text:is(button)(or rely on the existing.notif-quote-open:is(button)pattern).Two distinct buttons open the same notification —
src/lib/rebuild/NotifRow.svelteFor actionable rows with a post, both
.notif-row-text(the whole row) and.notif-quote-open(the excerpt) callonOpen?.(n). This creates redundant focusable targets and a duplicated "open" action in the a11y tree. Either expose a single activator or mark the secondary onetabindex="-1"/aria-hidden.Double notification load after clear —
src/routes/app/[...path]/+page.svelteclearNotificationsfirst runsloadNotifications(session, { replace: true })and then, infinally, unconditionally callsloadNotifications(session, { background: true }). The replace load already fetches authoritative state right after the clear; the second call is a duplicate network request in the common success path. Gate the background follow-up on a real signal (e.g., the replacement stream has opened with no fresh data) or skip it when the replace succeeded.CompactMediaPreviewportal lifecycle is fragile —src/lib/rebuild/CompactMediaPreview.svelteThe
portalaction appendsnodetodocument.bodyand removes it on destroy. Svelte also tries to remove the node from its (now-moved) parent during{#if fullPhoto}teardown. The current ordering works today, but it depends on Svelte calling the actiondestroybefore attempting DOM removal. Adding a comment or guarding the destroy to only remove when still attached would future-proof this against Svelte internals changes.aria-labelon visibility span may double-read —src/lib/rebuild/PostVisibility.svelteThe outer
<span>carriesaria-labelwhile wrapping anIconplus a visible<span>{details.label}</span>. IfIconexposes its own accessible name, AT users may hear the label twice. Ensure the innerIconisaria-hidden="true"(the component is not shown in the patch).Informational
timeline-catch-up.tsandreconcileTimelineCatchUpare intricate but accompanied by a substantial, focused Playwright suite covering multi-page catch-up, concurrent streamed posts, empty-timeline recovery, route retention, and stale local vs. federated races. The behavior matches the tests; future maintainers will benefit from inline comments explaining theinitialDataIds/initialQueuedIdsoverlap algorithm.notificationStreamGeneration, gatesapplyStreamedNotificationon both stream generation andnotificationClearState === 'clearing', and re-checksisCurrentSessionRequestafter eachawait. The in-flight-notification and delayed-stream tests exercise the important races.statusReplyTargetId/matchesStatusReplyTargetcorrectly route boosted-source identity through thread reconciliation, ancestor replies, and reply-target expansion. IndexingbyIdby bothidandstatusReplyTargetIdis safe under the assumption that source IDs are unique within a thread context.compactExcerptshortcode-boundary logic is exported and unit-tested, and is reused for chat excerpts after send — a nice consolidation of the priorchatExcerpthelper.openPleromaTimelineStreamchanges (open-timeout, detach-on-close, idempotent close) are well-covered by the rewritten client tests, including the new "socket never opens" replacement case.Overall
A large, well-structured patch that delivers a coherent set of features (fit-images, compact media previews with floating full-image view, notifications-page redesign, visibility badges, timeline stream catch-up, thread loading/scroll/restoration, count reconciliation, custom-emoji audit fixes, clear-all with generation-safe catch-up). Test coverage is thorough and traces cleanly to the per-issue acceptance criteria. No security, data-integrity, or correctness defects were identified. The most actionable items are the unbounded engagement-snapshot maps (Medium), the unthrottled floating-preview positioning (Medium), and a handful of low-severity UX/a11y/style nits listed above.
/oc rerun
/oc rerun
/oc rerun
/oc rerun
/oc rerun
/oc rerun
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.