Skip to content

340 local checklist notes#341

Merged
InfinityBowman merged 8 commits into
mainfrom
340-rob-bug-fix
Feb 1, 2026
Merged

340 local checklist notes#341
InfinityBowman merged 8 commits into
mainfrom
340-rob-bug-fix

Conversation

@InfinityBowman
Copy link
Copy Markdown
Owner

@InfinityBowman InfinityBowman commented Jan 29, 2026

Note

Medium Risk
Touches local checklist editing/persistence by changing how updates are merged and saved and by introducing a Y.Text-like adapter layer; bugs here could cause notes/comments to desync or overwrite state in IndexedDB. Auth changes are formatting-only.

Overview
Local checklists now support the same rich text note/comment editors as collaborative checklists by introducing LocalTextAdapter (a lightweight, Y.Text-compatible string adapter) and wiring adapter factories (getQuestionNote, getRob2Text, getRobinsText) through LocalChecklistView into ChecklistWithPdf/GenericChecklist.

Local checklist persistence is adjusted to reduce overwrite/race issues: the debounced save now persists the entire current checklist state when it fires, and adapter caches are cleared on load, on checklist updates, and on unmount to avoid stale text values.

Worker auth changes are limited to import/formatting cleanup in auth/config.ts and auth/oauth-relay.ts (no intended behavior changes).

Written by Cursor Bugbot for commit 33eb6d1. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Improvements

    • More reliable checklist text editing with synchronized local adapters and clearer cache invalidation.
    • Robust, argument-free save flow that reads current checklist state and reduces stale writes.
  • Bug Fixes

    • Clears adapter cache on load/unmount and before updates to prevent stale content and sync issues.
    • Improved error handling around saves.
  • Style

    • Formatting tweaks in authentication modules.

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

@InfinityBowman InfinityBowman linked an issue Jan 29, 2026 that may be closed by this pull request
@InfinityBowman InfinityBowman changed the title 340 rob bug fix 340 local checklist notes Jan 29, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 29, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds a local Y.Text-like adapter system for checklist text fields, integrates adapter factories into LocalChecklistView (changing debounced save to read current state and clearing adapter cache on load/update/unmount), and applies minor formatting changes to auth files.

Changes

Cohort / File(s) Summary
Text adapter implementation
packages/web/src/components/checklist/common/LocalTextAdapter.js
Adds LocalTextAdapter and createLocalAdapterFactories(getChecklist, updateState, save) — in-memory cache, adapter getters (getRob2Text, getQuestionNote, getRobinsText), observe/insert/delete API, clearCache and sync mechanisms.
Checklist integration
packages/web/src/components/checklist/LocalChecklistView.jsx
Wires adapter factories into component, replaces debouncedSave signature to read current checklist state (debounced save ignores args), clears adapter cache on load/update/unmount, and passes getQuestionNote, getRob2Text, getRobinsText to ChecklistWithPdf. Removes direct parameterized save calls.
Auth formatting changes
packages/workers/src/auth/config.ts, packages/workers/src/auth/oauth-relay.ts
Cosmetic/formatting edits: import line consolidation, simplified arrow callback syntax, condensed redirects/logging and minor whitespace rewrites; no functional changes.

Sequence Diagram

sequenceDiagram
    participant User
    participant LocalChecklistView
    participant LocalTextAdapterFactory as AdapterFactory
    participant LocalTextAdapter as Adapter
    participant DebouncedSave as debouncedSave
    participant UpdateChecklist as updateChecklist

    User->>LocalChecklistView: edit text / trigger update
    LocalChecklistView->>AdapterFactory: get<...> for path (lazy)
    AdapterFactory->>Adapter: return cached or new adapter
    Adapter->>LocalChecklistView: adapter.change -> updateState(...)
    LocalChecklistView->>AdapterFactory: clearCache() on load/update/unmount
    LocalChecklistView->>debouncedSave: invoke (no args)
    debouncedSave->>debouncedSave: wait (debounce)
    debouncedSave->>LocalChecklistView: call getChecklist()
    LocalChecklistView->>UpdateChecklist: updateChecklist(checklist)
    UpdateChecklist->>Adapter: external sync (_syncValue / observers)
    Adapter->>LocalChecklistView: observer notifications (value updated)
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly Related PRs

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title '340 local checklist notes' partially relates to the changeset. While the changes do involve local checklist functionality and text adapters for notes, the title is vague and doesn't clearly convey the main purpose—adding a local text adapter system for checklist fields. Consider a more descriptive title that explains the actual change, such as 'Add LocalTextAdapter for offline checklist note management' or 'Integrate local text adapters for checklist fields'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 340-rob-bug-fix

📜 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 7eb44c5 and 33eb6d1.

📒 Files selected for processing (2)
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/web/src/components/checklist/common/LocalTextAdapter.js

✏️ 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 29, 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 33eb6d1 Commit Preview URL Feb 01 2026, 12:08 AM

Comment thread packages/web/src/components/checklist/common/LocalTextAdapter.js Outdated
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: 2

🤖 Fix all issues with AI agents
In `@packages/web/src/components/checklist/common/LocalTextAdapter.js`:
- Around line 198-210: The forEach callbacks in _notifyUpdate and _syncValue use
concise arrow bodies causing implicit returns (lint error); update both observer
iterations in methods _notifyUpdate and _syncValue to use block arrow functions
instead (e.g., change callback => callback() to callback => { callback(); }) so
the callbacks have an explicit block body and no implicit return.

In `@packages/web/src/components/checklist/LocalChecklistView.jsx`:
- Around line 32-39: debouncedSave currently forwards only the last call's
arguments so partial updates from handleUpdate can overwrite earlier full-state
edits; change debouncedSave to always persist the component's current full
checklist state by merging incoming partial updates into the component's local
checklist state (use the component's checklist state variable) or by ignoring
args and reading the latest local state before calling
updateChecklist(params.checklistId, fullState), and apply the same change for
the other debounce usage around lines 104-115 so the backend always receives the
complete merged checklist state rather than a partial update.
🧹 Nitpick comments (1)
packages/web/src/components/checklist/LocalChecklistView.jsx (1)

215-227: Consider reducing ChecklistWithPdf prop surface.

Adding more adapter props increases coupling and makes the component harder to evolve. Consider passing a single adapters object or sourcing these adapters inside ChecklistWithPdf via a store or helper.

As per coding guidelines: Components should receive at most 1-5 props for local configuration only.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9187b17 and 7eb44c5.

📒 Files selected for processing (4)
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{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/workers/src/auth/config.ts
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/workers/src/auth/oauth-relay.ts
packages/workers/src/**/*.{js,ts,jsx,tsx}

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

ALWAYS use db.batch() for multiple related database operations in Drizzle to ensure atomicity - all operations must succeed or all fail together

Files:

  • packages/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
packages/workers/**/*.{js,ts}

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

packages/workers/**/*.{js,ts}: Always use createDomainError from @corates/shared for backend error handling instead of manually creating error objects
Use predefined error constants from @corates/shared (PROJECT_ERRORS, AUTH_ERRORS, VALIDATION_ERRORS, SYSTEM_ERRORS, USER_ERRORS) instead of arbitrary error strings
Wrap database operations in try-catch blocks and return domain errors using createDomainError with SYSTEM_ERRORS.DB_ERROR
Use validation middleware (validateRequest) for request validation instead of manually validating request bodies in routes

Files:

  • packages/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
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/workers/src/auth/config.ts
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/workers/src/auth/oauth-relay.ts
**/*.{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/workers/src/auth/config.ts
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/workers/src/auth/oauth-relay.ts
packages/workers/src/**/*.{ts,tsx}

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

packages/workers/src/**/*.{ts,tsx}: Use Zod for schema and input validation on backend services
Use Drizzle ORM for all database interactions and migrations
Use Better-Auth for authentication and user management
All project routes are org-scoped and use /api/orgs/:orgId/projects/... pattern in backend
Use requireOrgMembership and requireProjectAccess middleware for authentication in org-scoped routes
Never bypass Drizzle for database access

Never bypass Drizzle for database access - use Drizzle ORM for all database operations

Files:

  • packages/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
**/*

📄 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/workers/src/auth/config.ts
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/workers/src/auth/oauth-relay.ts
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/workers/src/auth/config.ts
  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
  • packages/workers/src/auth/oauth-relay.ts
packages/workers/src/**/*.ts

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

packages/workers/src/**/*.ts: Use Zod for schema and input validation in backend code
Use Drizzle ORM for ALL database interactions and migrations
Use Better-Auth for authentication and user management
Never bypass Drizzle for database access

Files:

  • packages/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
{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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
{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/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.jsx
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/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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/checklist/LocalChecklistView.jsx
🧠 Learnings (31)
📓 Common learnings
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
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
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 : Maintain separate answer format implementations for each checklist type (AMSTAR2, ROBINS-I, Generic) to prevent data corruption
📚 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/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
📚 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/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
📚 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/src/**/*.{ts,tsx} : Use import aliases from jsconfig.json as defined in the project configuration

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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/workers/src/auth/config.ts
  • packages/workers/src/auth/oauth-relay.ts
📚 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/web/src/**/*.{ts,tsx} : Use import aliases from jsconfig.json as defined for the project

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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/**/*.{ts,tsx,js,jsx} : Prefer config files over hardcoding values

Applied to files:

  • packages/workers/src/auth/config.ts
📚 Learning: 2026-01-05T01:00:58.113Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/workers-testing.mdc:0-0
Timestamp: 2026-01-05T01:00:58.113Z
Learning: Applies to {packages/workers/src/**/*.test.js,packages/workers/src/**/__tests__/**/*.js} : Reuse provided helpers from packages/workers/src/__tests__/helpers.js (resetTestDatabase, clearProjectDOs, seedUser, seedOrganization, createTestEnv, fetchApp, json, createAuthHeaders) instead of implementing ad-hoc solutions

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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} : Never prop-drill shared state - import stores directly

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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/web/src/**/*.{ts,tsx} : Never prop-drill shared state; import stores directly

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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 Drizzle ORM for ALL database interactions and migrations

Applied to files:

  • packages/workers/src/auth/config.ts
📚 Learning: 2026-01-17T16:10:07.531Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-17T16:10:07.531Z
Learning: Use required libraries for specific functionality: Zod for validation, Drizzle for database, Better-Auth for authentication, Ark UI for components

Applied to files:

  • packages/workers/src/auth/config.ts
📚 Learning: 2026-01-01T23:31:43.756Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.756Z
Learning: Applies to packages/workers/src/routes/**/*.js : Apply authentication and authorization middleware in correct order: Authentication → Organization membership → Project access → Authorization → Validation → Route handler

Applied to files:

  • packages/workers/src/auth/config.ts
📚 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/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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/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/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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 : Maintain separate answer format implementations for each checklist type (AMSTAR2, ROBINS-I, Generic) to prevent data corruption

Applied to files:

  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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 : Use getChecklistStatus utility from `@/lib/checklist-domain.js` to determine current checklist status before performing operations

Applied to files:

  • packages/web/src/components/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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,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/checklist/common/LocalTextAdapter.js
  • packages/web/src/components/checklist/LocalChecklistView.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} : Read Yjs-synced data from projectStore (using getStudies, getChecklist, etc.) rather than accessing Y.Doc maps/arrays directly

Applied to files:

  • packages/web/src/components/checklist/common/LocalTextAdapter.js
📚 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/checklist/LocalChecklistView.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/** : Use scoreChecklist utility from `@/ROBINS-I/checklist.js` to determine risk of bias rating: 'Low' | 'Moderate' | 'Serious' | 'Critical'

Applied to files:

  • packages/web/src/components/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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 `cachePdf` and `getCachedPdf` from `primitives/pdfCache.js` for caching PDF data in IndexedDB

Applied to files:

  • packages/web/src/components/checklist/LocalChecklistView.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/checklist/LocalChecklistView.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} : Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF

Applied to files:

  • packages/web/src/components/checklist/LocalChecklistView.jsx
📚 Learning: 2025-12-27T03:01:54.727Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/form-state.mdc:0-0
Timestamp: 2025-12-27T03:01:54.727Z
Learning: Applies to packages/web/src/**/*.{js,jsx} : 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()

Applied to files:

  • packages/workers/src/auth/oauth-relay.ts
🧬 Code graph analysis (2)
packages/web/src/components/checklist/common/LocalTextAdapter.js (1)
packages/web/src/components/checklist/LocalChecklistView.jsx (1)
  • createLocalAdapterFactories (42-47)
packages/web/src/components/checklist/LocalChecklistView.jsx (1)
packages/web/src/components/checklist/common/LocalTextAdapter.js (1)
  • createLocalAdapterFactories (17-152)
🪛 Biome (2.3.13)
packages/web/src/components/checklist/common/LocalTextAdapter.js

[error] 202-202: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)


[error] 209-209: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)

⏰ 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: Cursor Bugbot
  • GitHub Check: Workers Builds: corates
🔇 Additional comments (8)
packages/workers/src/auth/config.ts (1)

4-4: No issues to flag in this segment.

packages/workers/src/auth/oauth-relay.ts (4)

98-164: No issues to flag in this segment.


173-193: No issues to flag in this segment.


200-341: No issues to flag in this segment.


350-427: No issues to flag in this segment.

packages/web/src/components/checklist/common/LocalTextAdapter.js (2)

17-151: Factory-based adapters look consistent.

The path resolution and update shaping are coherent across checklist types, and the cache surface is straightforward to integrate.


176-182: Observer implementation is correct—callbacks intentionally receive no arguments.

LocalTextAdapter's observe() method invokes all registered callbacks with no parameters (callback()), and all existing consumers in NoteEditor.jsx and NotesCompareSection.jsx conform to this pattern by taking no parameters and reading state directly via yText.toString(). This is an intentional design choice for a simplified observer pattern. No code attempts to access event payloads or event.delta.

Likely an incorrect or invalid review comment.

packages/web/src/components/checklist/LocalChecklistView.jsx (1)

76-78: Cache clearing on load and unmount is a good guard against stale adapters.

This keeps adapter instances aligned with the latest checklist state.

Also applies to: 99-102

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

Comment on lines +198 to +210
_notifyUpdate() {
if (this._onUpdate) {
this._onUpdate(this._value);
}
this._observers.forEach(callback => callback());
}

// Allow external sync of value (e.g., when checklist reloads)
_syncValue(newValue) {
if (this._value !== newValue) {
this._value = newValue;
this._observers.forEach(callback => callback());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Biome lint error: avoid implicit returns in forEach callbacks.

Arrow expressions implicitly return, which triggers lint errors. Wrap callbacks in a block to avoid returning a value.

Proposed fix
-    this._observers.forEach(callback => callback());
+    this._observers.forEach(callback => {
+      callback();
+    });
@@
-      this._observers.forEach(callback => callback());
+      this._observers.forEach(callback => {
+        callback();
+      });
🧰 Tools
🪛 Biome (2.3.13)

[error] 202-202: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)


[error] 209-209: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)

🤖 Prompt for AI Agents
In `@packages/web/src/components/checklist/common/LocalTextAdapter.js` around
lines 198 - 210, The forEach callbacks in _notifyUpdate and _syncValue use
concise arrow bodies causing implicit returns (lint error); update both observer
iterations in methods _notifyUpdate and _syncValue to use block arrow functions
instead (e.g., change callback => callback() to callback => { callback(); }) so
the callbacks have an explicit block body and no implicit return.

Comment thread packages/web/src/components/checklist/LocalChecklistView.jsx Outdated
@InfinityBowman InfinityBowman merged commit d38323a into main Feb 1, 2026
2 of 4 checks passed
@InfinityBowman InfinityBowman deleted the 340-rob-bug-fix branch February 1, 2026 00:03
@github-actions github-actions Bot restored the 340-rob-bug-fix branch February 1, 2026 00:04
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

} catch (err) {
console.error('Error saving checklist:', err);
}
}, 500);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Race condition when navigating between checklists loses or corrupts data

High Severity

The refactored debouncedSave reads params.checklistId when it fires, not when scheduled. When navigating from checklist A to B, the pending save isn't cancelled in the createEffect. If the save fires during loading, it may save A's data to B's ID (data corruption). If it fires after loading completes, A's unsaved changes are lost. The old code captured checklistId at schedule time, avoiding this issue.

Additional Locations (1)

Fix in Cursor Fix in Web

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.

rob bug fix

2 participants