Skip to content

add presence#322

Merged
InfinityBowman merged 2 commits into
mainfrom
42-presence-during-reconcile
Jan 25, 2026
Merged

add presence#322
InfinityBowman merged 2 commits into
mainfrom
42-presence-during-reconcile

Conversation

@InfinityBowman
Copy link
Copy Markdown
Owner

@InfinityBowman InfinityBowman commented Jan 24, 2026

Summary by CodeRabbit

  • New Features
    • Real-time presence across reconciliation views showing who’s viewing each page
    • Stacked user avatars with tooltips, overflow +N indicator, and click-to-navigate behavior
    • Per-question presence indicators (pulsing rings) showing active viewers
    • Live remote cursors over scrollable content to see collaborators’ pointers
    • Deterministic user colors for consistent presence visuals

✏️ Tip: You can customize this high-level summary in your review settings.

@InfinityBowman InfinityBowman linked an issue Jan 24, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 24, 2026

📝 Walkthrough

Walkthrough

Adds real-time presence to reconciliation views: new UI components (avatars, pulsing rings, remote cursors), a presence hook using Yjs awareness, deterministic user color utilities, and wiring across reconciliation pages to surface who is viewing and where cursors are.

Changes

Cohort / File(s) Summary
Presence UI Components
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx, packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx, packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
Three new Solid components: stacked avatars with tooltips/overflow and click navigation; pulsing per-user rings for question pills; floating remote cursor labels positioned and adjusted for container scroll.
Presence Hook
packages/web/src/primitives/useReconciliationPresence.js
New hook that subscribes to Yjs awareness, manages local/remote presence state, throttles cursor updates, detects stale cursors, groups users by page, and exposes users/containers state.
Reconciliation Integrations
packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx, .../rob2-reconcile/ROB2ReconciliationWithPdf.jsx, .../robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
Wire presence into reconciliation views: add container refs, scroll tracking, overlay RemoteCursors, and show PresenceAvatars in headers; pass presence props into existing UI.
Navbar / Pills
packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
Navbar accepts usersByPage and passes usersOnPage to QuestionPill; QuestionPill tooltip augmented and non-current pills render QuestionPresenceIndicator.
Wrapper / Auth Wiring
packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
Use auth to build currentUser; forward getAwareness, currentUser, and checklistType to child reconciliation components.
Project Hook API
packages/web/src/primitives/useProject/index.js
Exposes new getAwareness() on the useProject return object for upstream presence coordination.
User Color Utility
packages/web/src/lib/userColors.js
New deterministic color palette and hash-based mapping utilities (PRESENCE_COLORS, getUserColor, getUserHexColor).

Sequence Diagram

sequenceDiagram
    participant Local as Local Client
    participant Awareness as Yjs Awareness
    participant Hook as useReconciliationPresence
    participant UI as Presence UI (Avatars/Cursors/Pills)
    participant Remote as Remote Client

    Local->>Awareness: publish local awareness (page, cursor, metadata)
    Awareness-->>Hook: awareness change event
    activate Hook
    Hook->>Hook: filter by checklistType, group usersByPage, compute visibleUsers
    Hook->>UI: emit remoteUsers, usersByPage, container scroll updates
    deactivate Hook

    UI->>UI: render PresenceAvatars, QuestionPresenceIndicator, RemoteCursors (positioned by scroll)
    
    Remote->>Awareness: publish remote awareness (page, cursor)
    Awareness-->>Hook: awareness change event
    activate Hook
    Hook->>UI: update cursors/avatars (stale detection/throttling applied)
    deactivate Hook

    UI->>Local: user clicks avatar -> navigate to target page (via navbarStore)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'add presence' is vague and generic, using non-descriptive terminology that lacks specificity about what presence features are being added or their scope within the reconciliation system. Consider a more specific title such as 'Add real-time presence indicators and remote cursors to reconciliation views' to better communicate the main changes to reviewers scanning the history.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 95.45% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 706806d and 0e33c25.

📒 Files selected for processing (1)
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Workers Builds: corates

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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 and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jan 24, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
corates 0e33c25 Commit Preview URL Jan 24 2026, 07:04 PM

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx`:
- Around line 19-21: visibleUsers calls props.users.slice and other spots read
props.users.length without guarding for undefined; update visibleUsers (and any
other uses like length checks around lines referenced) to treat users as an
empty array when absent (e.g., use props.users ?? [] or a local const users =
props.users ?? [] and then use users.slice and users.length) so .slice and
.length never throw during initial load; reference visibleUsers and maxRings
when making the change.
🧹 Nitpick comments (2)
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (2)

69-74: Redundant background-color styling on AvatarFallback.

The AvatarFallback applies both a Tailwind class (user.color.bg) and an inline style for background-color. The inline style will override the class, making the class ineffective. Consider removing the redundant class.

Suggested fix
                    <AvatarFallback
-                      class={`${user.color.bg} text-white`}
+                      class='text-white'
                      style={{ 'background-color': user.color.hex }}
                    >

60-66: Add explicit type="button" to prevent unintended form submissions.

The avatar button lacks an explicit type attribute. If this component is ever rendered inside a form, clicking it could trigger form submission.

Suggested fix
                <button
+                  type='button'
                  onClick={() => props.onUserClick?.(user.userId, user.currentPage)}
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5568627 and 706806d.

📒 Files selected for processing (11)
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/primitives/useReconciliationPresence.js
🧰 Additional context used
📓 Path-based instructions (14)
packages/web/src/**/*.{js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/form-state.mdc)

packages/web/src/**/*.{js,jsx}: Save form state to IndexedDB before initiating OAuth redirects (Google Drive, ORCID) using saveFormState() with form type ('createProject' or 'addStudies') and serializable state only
Only save serializable data to IndexedDB—exclude File objects, ArrayBuffers, functions, and other non-serializable objects from form state persistence
Restore form state after OAuth redirects by checking URL restore params with getRestoreParamsFromUrl(), retrieving saved state with getFormState(), restoring to form, clearing saved state with clearFormState(), and clearing URL params with clearRestoreParamsFromUrl()
For temporary File object storage during OAuth flows (e.g., pending PDFs), use projectStore.setPendingProjectData() instead of IndexedDB, as File objects cannot be serialized
Add restore parameters to the URL after OAuth redirects in the format '?restore=&projectId=' to signal form state restoration on mount
Clear URL restore parameters after form state restoration by calling clearRestoreParamsFromUrl() to prevent stale restoration attempts on subsequent navigation
Form state persistence library functions (saveFormState, getFormState, clearFormState, getRestoreParamsFromUrl, clearRestoreParamsFromUrl) are implemented in packages/web/src/lib/formStatePersistence.js and should be imported from @/lib/formStatePersistence.js

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/web/src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)

packages/web/src/**/*.{js,jsx,ts,tsx}: Always use uploadPdf from @api/pdf-api.js for uploading PDF files. Pass object with projectId, studyId, tag ('primary' or 'supplementary'), and fileName
Validate PDF files on frontend by checking file.type includes 'pdf' and file.size is within MAX_PDF_SIZE limit (full validation is done on backend)
Use cachePdf and getCachedPdf from @primitives/pdfCache.js for caching PDF data in IndexedDB
Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF
Store only PDF metadata in Yjs (id, name, size, tag, uploadedAt, uploadedBy), never store PDF binary data in Yjs as it is too large
Use importFromGoogleDrive from @api/google-drive.js for importing PDFs from Google Drive. Pass fileId, projectId, studyId, and tag
Save form state using saveFormState from @/lib/formStatePersistence.js before triggering OAuth redirects for Google Drive
Use addPdfToStudy operation from useProject hook to add PDFs to a study, passing id, name, size, tag, uploadedAt, and uploadedBy
Use removePdfFromStudy operation from useProject hook to remove PDFs from a study
Use pdfPreviewStore from @/stores/pdfPreviewStore.js for managing PDF preview state (openPreview, closePreview, getPreview methods)
Use downloadPdf from @api/pdf-api.js to download PDFs from server, then cache the result using cachePdf
Always cache PDFs after download and check cache before downloading to avoid redundant downloads
Use PDF operations from useProject hook instead of bypassing through direct API calls

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)

{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}: Use createSignal for simple reactive values in SolidJS components
Use createStore for complex objects and arrays that need granular reactivity in SolidJS
Use createMemo for computed/derived values that depend on reactive state in SolidJS
Always clean up SolidJS effects that create subscriptions or timers using onCleanup
Import stores directly in components and use store read/write action pattern - read from store, write via actions store
Prefer derived state with createMemo or signals over effects whenever possible
Use local createSignal or createStore for local component state; use external stores for shared/cross-feature state

{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}: NEVER destructure props in SolidJS components - it breaks reactivity. Access props directly (e.g., props.name) or wrap in a function (e.g., () => props.name)
Store imports should access store data directly from external stores (packages/web/src/stores/) rather than receiving store data via props
Use createSignal for simple, reactive values in SolidJS
Use createStore for complex objects and nested state in SolidJS, with nested updates using setState pattern (e.g., setState('items', items => [...items, newItem]))
Use createMemo for derived/computed values in SolidJS to maintain reactivity
Use local createSignal or createStore for local component state
Components should receive at most 1-5 props for local configuration only
Move business logic to stores, utilities, or SolidJS primitives rather than keeping it in component code

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/yjs-sync.mdc)

**/*.{js,jsx,ts,tsx}: Use the useProject hook for managing Yjs connections with reference counting instead of creating Y.Doc instances directly
Never create Y.Doc instances directly; always use the connection registry managed by useProject
Access Y.Doc connection state via projectStore.getConnectionState(projectId) instead of checking connection state directly
Read Yjs-synced data from projectStore (using getStudies, getChecklist, etc.) rather than accessing Y.Doc maps/arrays directly
Use operation functions from useProject or projectActionsStore for writing data instead of directly modifying Y.Doc
Don't store Y.Doc references in component state; always retrieve the connection through useProject
Handle connection cleanup via onCleanup() in Solid.js components or equivalent cleanup patterns, calling disconnect() when the component unmounts

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/web/src/**

📄 CodeRabbit inference engine (.cursor/rules/organizations.mdc)

packages/web/src/**: Use human-readable slug in frontend URLs: /orgs/:orgSlug/...
Use orgId (UUID) for API calls, not orgSlug, when making fetch requests to backend endpoints

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/web/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

packages/web/**/*.{js,ts,jsx,tsx}: Use apiFetch for all frontend API calls instead of raw fetch to automatically handle JSON parsing, errors, and toast notifications
Use handleFetchError for wrapping legacy raw fetch calls in frontend code (legacy pattern, prefer apiFetch)
Use error utility functions like isErrorCode from error-utils to check specific error types instead of direct string comparisons

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/{web,workers}/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

Never throw string literals; always throw Error objects or return domain errors from API routes

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
{packages/web/src/stores/**/*.{js,jsx,ts,tsx},packages/web/src/**/*.{js,jsx,ts,tsx}}

📄 CodeRabbit inference engine (.github/instructions/solidjs.instructions.md)

Shared or cross-feature state should use external stores located in packages/web/src/stores/

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/corates.mdc)

**/*.{js,ts,jsx,tsx}: Prefer modern ES6+ syntax and features
Comments should explain why something is being done, not what the code is doing
Reserve comments for explaining intent, context, workarounds, assumptions, edge cases, or limitations
Use TODO(agent): prefix for incomplete work or flagged items with brief description and relevant doc references

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
**/*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Never use emojis or unicode symbols anywhere in code, comments, documentation, plan files, commit messages, or examples

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/**/*.{ts,tsx,js,jsx}: Prefer modern ES6+ syntax and features
Prefer config files over hardcoding values
Keep files small, focused, and modular - extract large files into sub-modules or separate utilities
Each file should handle one coherent responsibility
Comments should explain WHY something is being done or provide context, not repeat what the code is saying
Do NOT narrate what code is doing, don't duplicate function/variable names in comments, and don't leave stale comments that contradict the code
Use the Agent TODO convention // TODO(agent): Brief description for incomplete work, flagging items for future attention, known limitations, and documentation section references

Use TODO(agent) convention with brief description and relevant doc section references for incomplete work or flagged issues

Files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/lib/userColors.js
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
packages/web/src/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)

Use PdfViewer component from @/components/checklist-ui/pdf/PdfViewer.jsx for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange

Files:

  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)

{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}: NEVER destructure props in SolidJS components - access props directly or wrap in functions to maintain reactivity
Use external stores in packages/web/src/stores/ for shared/cross-feature state instead of prop-drilling
Keep SolidJS components lean and focused on rendering - move business logic to stores, primitives, or utilities
Create reusable logic in primitives (hooks) in packages/web/src/primitives/ and import them into components
Use Solid's Show component for conditional rendering instead of ternary operators
Use Solid's For component for rendering lists instead of Array.map()
Use the children helper when manipulating props.children in SolidJS components

Use Show and For components for conditional and list rendering in SolidJS

Files:

  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
packages/web/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

Use createFormErrorSignals for form error handling in frontend forms to manage field-level and global error states

Files:

  • packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx
  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
🧠 Learnings (38)
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use the `useProject` hook for managing Yjs connections with reference counting instead of creating Y.Doc instances directly

Applied to files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
📚 Learning: 2025-12-27T03:01:35.601Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/durable-objects.mdc:0-0
Timestamp: 2025-12-27T03:01:35.601Z
Learning: Applies to packages/workers/src/durable-objects/**/ProjectDoc.{js,ts} : Use y-websocket protocol with message type 1 for awareness (presence) messages in ProjectDoc

Applied to files:

  • packages/web/src/primitives/useProject/index.js
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
📚 Learning: 2026-01-01T23:32:17.698Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/organizations.mdc:0-0
Timestamp: 2026-01-01T23:32:17.698Z
Learning: Applies to packages/web/src/primitives/useOrg* : Use useOrgProjectContext hook to combine org and project context, providing basePath and path builder functions (getStudyPath, getChecklistPath)

Applied to files:

  • packages/web/src/primitives/useProject/index.js
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Access Y.Doc connection state via projectStore.getConnectionState(projectId) instead of checking connection state directly

Applied to files:

  • packages/web/src/primitives/useProject/index.js
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/primitives/useProject/checklists.js : Store question notes as Y.Text objects obtained from useProject hook via getQuestionNote operation to enable collaborative editing

Applied to files:

  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to packages/web/src/components/checklist-ui/compare/** : Use Y.Text objects for collaborative editing of question notes in reconciliation

Applied to files:

  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use Solid's Show component for conditional rendering instead of ternary operators

Applied to files:

  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
📚 Learning: 2026-01-17T00:25:12.518Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/instructions/solidjs.instructions.md:0-0
Timestamp: 2026-01-17T00:25:12.518Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use Show and For components for conditional and list rendering in SolidJS

Applied to files:

  • packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use `PdfViewer` component from `@/components/checklist-ui/pdf/PdfViewer.jsx` for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/lib/checklist-domain.js} : Store reconciliation progress metadata (IDs and optional currentPage) in the study's Y.Map reconciliation property

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/lib/checklist-domain.js,packages/web/src/AMSTAR2/checklist-compare.js} : Store final answers in the reconciled checklist itself, not in reconciliation progress metadata

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `pdfPreviewStore` from `@/stores/pdfPreviewStore.js` for managing PDF preview state (openPreview, closePreview, getPreview methods)

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/ROBINS-I/** : ROBINS-I answers must use string format: 'Y' | 'PY' | 'PN' | 'N' | 'NI' | 'NA' with optional comment field

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js,packages/web/src/primitives/useProject/checklists.js : Use checklist operations from useProject hook (createChecklist, updateChecklistAnswer, getChecklistData) instead of manually updating checklist structure

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
  • packages/web/src/primitives/useReconciliationPresence.js
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Use getChecklistStatus utility from `@/lib/checklist-domain.js` to determine current checklist status before performing operations

Applied to files:

  • packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/** : Use NoteEditor component from `@/components/checklist-ui/common/NoteEditor.jsx` for question note editing with max 2000 character limit

Applied to files:

  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/AMSTAR2/checklist-compare.js} : Use compareChecklists utility from checklist-compare.js for comparing reviewer checklists

Applied to files:

  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to packages/web/src/components/checklist-ui/compare/** : Use SingleQuestionPage component for standard single-part questions (q1-q8, q10, q12-q16)

Applied to files:

  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Checklist status transitions follow sequence: in_progress → completed (when all questions answered) → reconciled (after reconciliation complete)

Applied to files:

  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/lib/checklist-domain.js : Register and retrieve checklists using checklist-registry: getChecklistType and getChecklistComponent functions

Applied to files:

  • packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/lib/checklist-domain.js,packages/web/src/AMSTAR2/checklist-compare.js} : Reconciliation structure should contain checklist1Id, checklist2Id, and reconciledChecklistId

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx
📚 Learning: 2026-01-17T00:25:35.716Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-17T00:25:35.716Z
Learning: Applies to packages/workers/src/**/*.{ts,tsx} : Use Better-Auth for authentication and user management

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use operation functions from useProject or projectActionsStore for writing data instead of directly modifying Y.Doc

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2026-01-17T16:09:36.920Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-17T16:09:36.920Z
Learning: Applies to packages/workers/src/**/*.ts : Use Better-Auth for authentication and user management

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2026-01-17T00:25:35.716Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-17T00:25:35.716Z
Learning: Applies to packages/workers/src/**/*.{ts,tsx} : Use `requireOrgMembership` and `requireProjectAccess` middleware for authentication in org-scoped routes

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to packages/web/src/primitives/useProject/**, packages/web/src/stores/projectStore.js : When access is denied (user removed or project deleted), the connection automatically triggers cleanup: IndexedDB data cleared, connection closed, store cleared, and user redirected

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Use local createSignal or createStore for local component state; use external stores for shared/cross-feature state

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2026-01-17T16:09:36.920Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-17T16:09:36.920Z
Learning: Applies to packages/{web,landing}/src/**/*.{ts,tsx} : Use `createStore` for complex state objects in SolidJS

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't store Y.Doc references in component state; always retrieve the connection through useProject

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2026-01-17T00:25:12.518Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/instructions/solidjs.instructions.md:0-0
Timestamp: 2026-01-17T00:25:12.518Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Use createStore for complex objects and nested state in SolidJS, with nested updates using setState pattern (e.g., setState('items', items => [...items, newItem]))

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:01:35.601Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/durable-objects.mdc:0-0
Timestamp: 2025-12-27T03:01:35.601Z
Learning: Applies to packages/workers/src/durable-objects/**/ProjectDoc.{js,ts} : Check user membership in project before allowing WebSocket connection in ProjectDoc

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:50.087Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/yjs-sync.mdc:0-0
Timestamp: 2025-12-27T03:02:50.087Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Never create Y.Doc instances directly; always use the connection registry managed by useProject

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/** : Handle multi-part AMSTAR2 questions correctly: q9 (parts a, b), q11 (parts a, b) require separate answer entries

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/** : AMSTAR2 answers must use matrix format: array of column arrays with boolean values representing checkbox selections per column

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/** : Use scoreChecklist utility from `@/AMSTAR2/checklist.js` to determine quality assessment rating: 'High' | 'Moderate' | 'Low' | 'Critically Low'

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/lib/checklist-domain.js} : Multi-part answers (q9a, q9b, q11a, q11b) should be stored as objects with answer matrix and critical flag properties

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to packages/web/src/components/checklist-ui/compare/** : Use multiPartAnswersEqual helper to compare multi-part answers between reviewers

Applied to files:

  • packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Create reusable logic in primitives (hooks) in packages/web/src/primitives/ and import them into components

Applied to files:

  • packages/web/src/primitives/useReconciliationPresence.js
🧬 Code graph analysis (5)
packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx (2)
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (1)
  • visibleUsers (30-30)
packages/web/src/lib/userColors.js (1)
  • index (69-69)
packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx (4)
packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx (3)
  • containerRef (50-50)
  • containerScrollY (51-51)
  • presence (69-75)
packages/web/src/primitives/useReconciliationPresence.js (1)
  • useReconciliationPresence (30-251)
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (1)
  • PresenceAvatars (28-108)
packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx (1)
  • RemoteCursors (44-92)
packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx (2)
packages/web/src/components/project/reconcile-tab/amstar2-reconcile/navbar-utils.js (1)
  • getQuestionTooltip (59-70)
packages/web/src/components/project/reconcile-tab/QuestionPresenceIndicator.jsx (1)
  • QuestionPresenceIndicator (18-62)
packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx (4)
packages/web/src/primitives/useReconciliationPresence.js (1)
  • useReconciliationPresence (30-251)
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (1)
  • PresenceAvatars (28-108)
packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx (1)
  • Navbar (30-47)
packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx (1)
  • RemoteCursors (44-92)
packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx (4)
packages/web/src/components/checklist/AMSTAR2Checklist/AMSTAR2Checklist.jsx (3)
  • containerRef (344-344)
  • containerRef (474-474)
  • containerRef (677-677)
packages/web/src/primitives/useReconciliationPresence.js (1)
  • useReconciliationPresence (30-251)
packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (1)
  • PresenceAvatars (28-108)
packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx (1)
  • RemoteCursors (44-92)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Workers Builds: corates
  • GitHub Check: prettier
🔇 Additional comments (19)
packages/web/src/primitives/useProject/index.js (1)

371-373: Awareness accessor looks good.

Exposing awareness through the connection manager keeps the Yjs access centralized and guarded.

packages/web/src/lib/userColors.js (1)

67-71: Deterministic color mapping looks solid.

The hash-based selection provides stable user colors with a clear fallback.

packages/web/src/components/project/reconcile-tab/RemoteCursors.jsx (1)

44-90: Cursor overlay implementation looks good.

Scroll-adjusted positioning and pointer-events-none are appropriate for this overlay use case.

packages/web/src/components/project/reconcile-tab/robins-i-reconcile/RobinsIReconciliationWithPdf.jsx (1)

69-146: Presence wiring in the reconciliation panel looks good.

The container ref and scroll tracking integrate cleanly with the presence hook and cursor overlay.

packages/web/src/primitives/useReconciliationPresence.js (1)

55-206: The concern about awareness reactivity is not applicable here. The parent ProjectView calls useProject(projectId) which automatically establishes the connection before rendering child routes. Since the connection and awareness are created synchronously during connect(), and ReconciliationWrapper only mounts after its parent has initialized, awareness is guaranteed to be available when useReconciliationPresence runs. The early return pattern (if (!aw) return) is appropriate defensive programming. No changes needed.

packages/web/src/components/project/reconcile-tab/PresenceAvatars.jsx (1)

28-51: LGTM - Clean reactive patterns.

The component correctly uses reactive getters (maxVisible, visibleUsers, overflowCount) and accesses props directly without destructuring, maintaining SolidJS reactivity. The avatar URL construction logic handles both full URLs and API paths appropriately.

packages/web/src/components/project/reconcile-tab/rob2-reconcile/ROB2ReconciliationWithPdf.jsx (3)

69-76: LGTM - Presence hook integration follows correct patterns.

The presence hook is correctly configured with reactive getters for all options (getAwareness, getCurrentPage, checklistType, currentUser, containerRef). This ensures proper reactivity tracking and cleanup is handled internally by the hook via onCleanup.


140-161: LGTM - Container and cursor overlay structure is correct.

The container properly uses relative positioning with overflow-auto, and the RemoteCursors overlay is positioned correctly within it. The scroll handler updates containerScrollY which is passed to RemoteCursors for proper cursor position adjustment.


108-118: LGTM - Presence avatars integration in header.

The presence avatars are correctly wired to navigate to the clicked user's page via navbarStore.goToPage. The getPageLabel uses "Item" which is appropriate for ROB2 terminology.

packages/web/src/components/project/reconcile-tab/amstar2-reconcile/Navbar.jsx (3)

33-41: LGTM - Correct prop passing pattern for presence data.

The usersByPage Map is accessed correctly with .get(index()) and falls back to an empty array. Props are accessed directly without destructuring, maintaining SolidJS reactivity.


66-74: LGTM - Tooltip enhancement with viewer names.

The tooltip correctly combines base tooltip info with viewer names using a pipe separator. Using createMemo ensures efficient recomputation only when dependencies change.


85-88: LGTM - Presence indicator placement.

The QuestionPresenceIndicator is correctly rendered only for non-current pages, avoiding visual clutter on the active page. The component placement inside the button ensures proper visual association.

packages/web/src/components/project/reconcile-tab/ReconciliationWithPdf.jsx (3)

68-80: LGTM - Presence hook and scroll tracking setup.

The presence hook configuration and scroll handling follow correct SolidJS patterns. All options use reactive getters, and the scroll handler properly updates containerScrollY.


107-122: LGTM - Header presence integration.

The presence avatars and navbar integration is correct. The onUserClick correctly uses goToQuestion for AMSTAR2 navigation, and usersByPage() is properly invoked to pass the memo value.


139-162: LGTM - Container and reconciliation panel structure.

The container correctly wraps the reconciliation content with the RemoteCursors overlay. The structure matches the ROB2 version, ensuring consistent presence behavior across checklist types.

packages/web/src/components/project/reconcile-tab/ReconciliationWrapper.jsx (4)

60-69: LGTM - Current user memo for presence.

The currentUser memo correctly derives user information from the authenticated user, returning null when not available. The structure matches what useReconciliationPresence expects (id, name, image).


513-516: LGTM - Presence props correctly passed to reconciliation components.

The getAwareness, currentUser, and checklistType props are consistently passed to all three reconciliation components. The currentUser is correctly passed as a memo reference (not invoked), allowing child components to maintain reactivity.


549-551: LGTM - ROB2 presence props.

Consistent with AMSTAR2, the ROB2 reconciliation receives the same presence props with the appropriate checklistType='ROB2'.


586-588: LGTM - ROBINS_I presence props.

Consistent with the other reconciliation types, ROBINS_I receives the same presence props with checklistType='ROBINS_I'.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@InfinityBowman InfinityBowman merged commit 8ca5f39 into main Jan 25, 2026
3 checks passed
@InfinityBowman InfinityBowman deleted the 42-presence-during-reconcile branch January 25, 2026 00:02
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.

Presence during reconcile

1 participant