Skip to content

250 even smarter robins#271

Merged
InfinityBowman merged 6 commits into
mainfrom
250-even-smarter-robins
Jan 10, 2026
Merged

250 even smarter robins#271
InfinityBowman merged 6 commits into
mainfrom
250-even-smarter-robins

Conversation

@InfinityBowman
Copy link
Copy Markdown
Owner

@InfinityBowman InfinityBowman commented Jan 10, 2026

Summary by CodeRabbit

  • New Features

    • Implemented smart early-exit UI flow for ROBINS-I with optional questions after auto-scoring completes.
    • Redesigned question interface with button-based options replacing radio inputs.
    • Added visual "Optional" indicator and reduced opacity styling for skippable questions.
    • Introduced Section D metadata for information sources documentation.
    • Enhanced ROBINS-I validation to require overall judgment completion.
  • Tests

    • Added test coverage for ROBINS-I completion logic validation.

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

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

coderabbitai Bot commented Jan 10, 2026

📝 Walkthrough

Walkthrough

Implements a smart early-exit UI flow for ROBINS-I checklists using the existing scoring engine's completion signal. Updates validation logic to require both domain and overall judgements, introduces skippable question indicators across domain and signalling question components, and adds Section D schema definition for information sources.

Changes

Cohort / File(s) Summary
ROBINS-I Completion Logic
packages/shared/src/checklists/robins-i/answers.ts, packages/shared/src/checklists/__tests__/robins-i.test.ts
Modified isROBINSIComplete to require both domain-level and overall judgements; split logic into domainsComplete and overallComplete checks. Added test cases verifying completion conditions.
Schema Extensions
packages/shared/src/checklists/robins-i/schema.ts
Introduced SECTION_D constant defining metadata for information sources section with title, description, and otherField configuration.
Checklist Validation Integration
packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
Integrated ROBINS-I validation via isROBINSIComplete alongside existing AMSTAR2 validation; implemented type-aware conditional validation paths with corresponding user feedback messages distinguishing checklist types.
Smart Early-Exit UI Components
packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx, packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
Added early completion detection and per-question skippability predicates in DomainSection; enhanced SignallingQuestion with button-based UI, optional indicator label, dynamic opacity styling, toggle-to-clear answer logic, and refined NA/NI coercion.
Linting Cleanup
packages/workers/worker-configuration.d.ts
Removed two eslint-disable-line comments without signature changes.

Possibly related PRs

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% 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 '250 even smarter robins' is vague and generic, using non-descriptive terms that don't convey meaningful information about the changeset, which involves implementing a smart early-exit UI flow for ROBINS-I. Replace with a clear, specific title such as 'Implement smart early-exit UI flow for ROBINS-I' or 'Add optional question skipping based on auto-scoring completion' to better describe the primary change.
✅ 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

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.

@InfinityBowman InfinityBowman merged commit ca789c1 into main Jan 10, 2026
1 of 3 checks passed
@InfinityBowman InfinityBowman deleted the 250-even-smarter-robins branch January 10, 2026 00:22
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/checklist/ChecklistYjsWrapper.jsx:
- Around line 353-369: The current createMemo isChecklistValid uses a silent
fallback (return true) for unknown checklistType values, which will allow future
unhandled types to be marked complete; update the logic in isChecklistValid
(which reads checklistType() and checklistForUI()) to detect unknown types by
consulting the registry (e.g., call getChecklistConfig(checklistType()) or check
CHECKLIST_REGISTRY) and either log a warning with the type (console.warn or
process/logger) or throw an error instead of returning true, and ensure existing
branches still call isAMSTAR2Complete(checklist) and
isROBINSIComplete(checklist).
🧹 Nitpick comments (2)
packages/shared/src/checklists/__tests__/robins-i.test.ts (1)

253-292: Good test coverage for the new completion logic.

The tests correctly verify the updated behavior where both domain judgements and overall judgement are required for completion.

Optional: Consider adding an edge case test

You might add a test where checklist.overall exists but judgement is explicitly null to ensure the logic handles this case:

it('should return false when overall exists but judgement is null', () => {
  const checklist = createROBINSIChecklist({
    name: 'Test',
    id: 'test-123',
  });

  // Set all domain judgements
  checklist.domain1a = { answers: {}, judgement: 'Low', judgementSource: 'auto' };
  checklist.domain2 = { answers: {}, judgement: 'Low', judgementSource: 'auto' };
  checklist.domain3 = { answers: {}, judgement: 'Low', judgementSource: 'auto' };
  checklist.domain4 = { answers: {}, judgement: 'Low', judgementSource: 'auto' };
  checklist.domain5 = { answers: {}, judgement: 'Low', judgementSource: 'auto' };
  checklist.domain6 = { answers: {}, judgement: 'Low', judgementSource: 'auto' };

  // Set overall but with null judgement
  checklist.overall = {
    judgement: null,
    judgementSource: 'auto',
    direction: null,
  };

  expect(isROBINSIComplete(checklist)).toBe(false);
});
packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx (1)

68-80: Consider accessibility implications of button-based radio replacement.

The button-based UI is a nice UX improvement, but replacing native radio inputs with buttons removes semantic radio group behavior. Consider:

  1. Adding role="radiogroup" to the container (or parent)
  2. Adding role="radio" and aria-checked to buttons
  3. Implementing proper keyboard navigation (arrow keys for radio-like groups)
  4. Verifying screen reader announcements are clear

The current implementation has helpful title tooltips but may not provide the expected screen reader experience.

♻️ Suggested accessibility enhancements

Add ARIA attributes to the button:

 <button
   type='button'
   onClick={() => !props.disabled && handleAnswerChange(option)}
   disabled={props.disabled}
+  role='radio'
+  aria-checked={props.answer?.answer === option}
   class={`relative inline-flex cursor-pointer items-center justify-center rounded border px-2 py-1 text-xs font-medium transition-colors ${props.disabled ? 'cursor-not-allowed opacity-50' : ''} ${
     props.answer?.answer === option ?
       'border-blue-400 bg-blue-100 text-blue-800'
     : 'border-gray-200 bg-gray-50 text-gray-600 hover:bg-gray-100'
   } `}
   title={RESPONSE_LABELS[option]}
 >
   {option}
 </button>

And consider adding role="radiogroup" to the options container:

-<div class='flex shrink-0 flex-wrap gap-1 sm:gap-2'>
+<div class='flex shrink-0 flex-wrap gap-1 sm:gap-2' role='radiogroup'>
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de37c6f and 45e9009.

📒 Files selected for processing (8)
  • packages/docs/plans/robins-i-smart-flow.md
  • packages/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/workers/worker-configuration.d.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

**/*.{js,jsx,ts,tsx}: For UI icons, use solid-icons library or SVGs only (never emojis)
Prefer modern ES6+ syntax and features
Use import aliases from jsconfig.json (see ui-components.mdc)
Group related components in subdirectories with barrel exports
Use Ark UI components from @corates/ui package, NOT local components
Use solid-icons icon library (e.g., solid-icons/bi, solid-icons/fi) for icons
Comments should explain WHY something is being done, not narrate what the code does
Use comments to explain why a particular approach or workaround was chosen
Use comments to clarify intent when code could be misread or misunderstood
Use comments to provide context from external systems, specs, or requirements
Use comments to document assumptions, edge cases, or limitations
Do NOT narrate what the code is doing in comments
Do NOT duplicate function or variable names in plain English in comments
Do NOT leave stale comments that contradict the code
Do NOT reference removed or obsolete code paths in comments

**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Comments should not repeat what the code is saying. Rese...

Files:

  • packages/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/workers/worker-configuration.d.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
**/*.{js,jsx,ts,tsx,css,scss}

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

Ensure browser compatibility (Safari is usually problematic)

Files:

  • packages/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/workers/worker-configuration.d.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.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/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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

packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use solid-icons library or SVGs only (never emojis)
Use import aliases from jsconfig.json (see ui-components.mdc)

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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

packages/web/src/**/*.{jsx,tsx}: Do NOT prop-drill application state - Import stores directly where needed
Do NOT destructure props - Access props.field directly or wrap in function: () => props.field
Components should receive at most 1-5 props (local config only, not shared state)
Move business logic to stores, utilities, or primitives (not components)

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/{web,ui}/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

packages/{web,ui}/**/*.{js,jsx,ts,tsx}: Import UI components from '@corates/ui' package instead of local components directories
Use solid-icons library for icons instead of emojis or other icon sources
Use Tailwind CSS classes for styling UI components
Apply responsive design using mobile-first approach with Tailwind CSS

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/web/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

Use import aliases from jsconfig.json (e.g., @/, @components/, @auth-ui/, @checklist-ui/, @project-ui/, @routes/, @primitives/, @api/, @config/, @lib/) instead of relative paths

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/web/**/*.{jsx,tsx}

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

packages/web/**/*.{jsx,tsx}: Do NOT prop-drill application state in SolidJS - import stores directly where needed
Do NOT destructure props in SolidJS - access props.field directly or wrap in function: () => props.field
Shared state lives in external stores under packages/web/src/stores/
SolidJS components should receive at most 1-5 props (local config only, not shared state)
Use createStore for complex state objects in SolidJS
Use createMemo for derived values in SolidJS
Move business logic to stores, utilities, or primitives - not components
Frontend uses orgSlug in URLs (/orgs/:orgSlug/...) for readability

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

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/{web,ui}/src/**/*.{js,jsx,ts,tsx}

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

Group related components in subdirectories with barrel exports

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/{workers,web}/src/**/*.{js,ts,jsx,tsx}

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

Use Better-Auth for authentication and user management

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/{web,landing,docs}/src/**/*.{jsx,tsx}

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

packages/{web,landing,docs}/src/**/*.{jsx,tsx}: Use Ark UI components from @corates/ui package, NOT local components
Use solid-icons for icon imports (e.g., solid-icons/bi, solid-icons/fi)

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/web/src/**/*.{js,ts,jsx,tsx}

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

packages/web/src/**/*.{js,ts,jsx,tsx}: Use createStore for complex state objects
Use createMemo for derived values

Files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.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/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
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/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/workers/worker-configuration.d.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
packages/workers/**/*.{js,ts}

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

packages/workers/**/*.{js,ts}: Use Zod for schema and input validation on the backend
Use Drizzle ORM for ALL database interactions and migrations
Use Better-Auth for authentication and user management
All project routes are org-scoped - use /api/orgs/:orgId/projects/... pattern on backend
Backend uses orgId (UUID) for all API operations
Use requireOrgMembership and requireProjectAccess middleware for auth

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/worker-configuration.d.ts
🧠 Learnings (26)
📓 Common learnings
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 shouldStopAssessment utility from @/ROBINS-I/checklist.js to check if Section B indicates critical risk of bias requiring assessment termination
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'
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)
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
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
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
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'
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
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
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
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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 shouldStopAssessment utility from @/ROBINS-I/checklist.js to check if Section B indicates critical risk of bias requiring assessment termination

Applied to files:

  • packages/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/schema.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/shared/src/checklists/__tests__/robins-i.test.ts
  • packages/shared/src/checklists/robins-i/answers.ts
📚 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/checklist/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx
  • packages/shared/src/checklists/robins-i/answers.ts
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/checklist/ROBINSIChecklist/SignallingQuestion.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/checklist/ROBINSIChecklist/SignallingQuestion.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/ROBINSIChecklist/SignallingQuestion.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/ROBINSIChecklist/SignallingQuestion.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} : Use Solid's Show component for conditional rendering instead of ternary operators

Applied to files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.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} : Use Solid's For component for rendering lists instead of Array.map()

Applied to files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.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/ROBINSIChecklist/SignallingQuestion.jsx
  • packages/web/src/components/checklist/ChecklistYjsWrapper.jsx
📚 Learning: 2026-01-01T23:32:06.095Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.095Z
Learning: Applies to packages/web/**/*.{jsx,tsx} : Use `createMemo` for derived values in SolidJS

Applied to files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.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 createMemo for computed/derived values that depend on reactive state in SolidJS

Applied to files:

  • packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.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/ChecklistYjsWrapper.jsx
  • packages/docs/plans/robins-i-smart-flow.md
📚 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/ChecklistYjsWrapper.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/** : Auto-fill final answer with reviewer1's answer when reviewers agree and no final answer exists

Applied to files:

  • packages/web/src/components/checklist/ChecklistYjsWrapper.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/checklist/ChecklistYjsWrapper.jsx
📚 Learning: 2026-01-01T23:32:06.095Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.095Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Do NOT reference removed or obsolete code paths in comments

Applied to files:

  • packages/workers/worker-configuration.d.ts
🧬 Code graph analysis (4)
packages/shared/src/checklists/__tests__/robins-i.test.ts (2)
packages/shared/src/checklists/robins-i/create.ts (1)
  • createROBINSIChecklist (42-123)
packages/shared/src/checklists/robins-i/answers.ts (1)
  • isROBINSIComplete (188-210)
packages/shared/src/checklists/robins-i/schema.ts (1)
packages/web/src/components/checklist/ROBINSIChecklist/checklist-map.js (2)
  • SECTION_D (27-27)
  • SECTION_D (27-27)
packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx (2)
packages/shared/src/checklists/robins-i/schema.ts (2)
  • getResponseOptions (619-621)
  • RESPONSE_LABELS (27-38)
packages/web/src/components/checklist/ROBINSIChecklist/checklist-map.js (4)
  • getResponseOptions (44-44)
  • getResponseOptions (44-44)
  • RESPONSE_LABELS (15-15)
  • RESPONSE_LABELS (15-15)
packages/web/src/components/checklist/ChecklistYjsWrapper.jsx (4)
packages/web/src/components/checklist/GenericChecklist.jsx (1)
  • checklistType (32-40)
packages/web/src/components/checklist/AMSTAR2Checklist/checklist.js (2)
  • isAMSTAR2Complete (15-15)
  • isAMSTAR2Complete (15-15)
packages/shared/src/checklists/robins-i/answers.ts (1)
  • isROBINSIComplete (188-210)
packages/web/src/components/checklist/ROBINSIChecklist/checklist.js (2)
  • isROBINSIComplete (13-13)
  • isROBINSIComplete (13-13)
🪛 LanguageTool
packages/docs/plans/robins-i-smart-flow.md

[grammar] ~62-~62: Use a hyphen to join words.
Context: ...relevant --- ## Requirements ### Must Have 1. **Visual indication when a doma...

(QB_NEW_EN_HYPHEN)


[style] ~67-~67: The words ‘explaining’ and ‘explanation’ are quite similar. Consider replacing ‘explaining’ with a different word.
Context: ...mentation purposes 4. Clear messaging explaining why questions are skipped - Brief exp...

(VERB_NOUN_SENT_LEVEL_REP)

🪛 markdownlint-cli2 (0.18.1)
packages/docs/plans/robins-i-smart-flow.md

11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


235-235: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


245-245: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


309-309: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ 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
🔇 Additional comments (16)
packages/workers/worker-configuration.d.ts (2)

9324-9328: No concerns: AIGatewayUniversalRequest.provider typing remains compatible.
Looks like a lint-only tweak; keeping AIGatewayProviders | string preserves flexibility for non-enum provider values.


9331-9342: No concerns: AiGateway.getUrl() signature unchanged.
This appears to be removing inline lint suppression without affecting the declaration surface. Since this file is generated, just ensure it’s updated via wrangler types to prevent future drift.

packages/shared/src/checklists/robins-i/schema.ts (1)

92-100: LGTM - Clean schema extension.

The SECTION_D constant provides well-structured metadata for the information sources section, following the existing schema patterns. The structure with title, description, and otherField configuration is consistent and clear.

packages/docs/plans/robins-i-smart-flow.md (1)

1-327: Well-structured implementation plan.

The documentation clearly outlines the smart early-exit UI flow, leveraging the existing scoring engine's completion signal. The phased approach and visual design examples provide good implementation guidance. The static analysis hints about code block language tags and hyphenation are minor formatting nitpicks that don't affect clarity.

packages/web/src/components/checklist/ROBINSIChecklist/DomainSection.jsx (2)

31-39: Clean implementation of early completion detection.

The logic correctly identifies when a domain's scoring is complete and which questions can be skipped. The isEarlyComplete memo leverages the existing scoring engine's completion signal, and isQuestionSkippable appropriately checks both completion status and answer presence.


188-188: Correct prop threading to SignallingQuestion.

The isSkippable prop is properly passed to SignallingQuestion in both render paths (with and without subsections), enabling the UI to display optional question indicators as designed.

Also applies to: 214-214

packages/shared/src/checklists/robins-i/answers.ts (1)

186-209: UI properly guides users to set overall judgement and handles the new completion requirement gracefully.

The verification confirms the implementation is well-structured: OverallSection.jsx displays completion status ("Incomplete" when missing), provides a "Complete all domains" message, and offers both auto-calculated and manual judgement selection. The handleToggleComplete() function in ChecklistYjsWrapper.jsx protects form submission by validating isROBINSIComplete() before allowing completion, showing users a specific error message: "An overall risk of bias judgement must be set before marking the checklist as complete." Existing checklists will correctly show as incomplete only if overall judgement is missing—this is intentional validation, not a side effect, and is covered by tests.

packages/web/src/components/checklist/ChecklistYjsWrapper.jsx (3)

23-23: LGTM!

The import follows the established pattern for AMSTAR2 completion checking and correctly uses the import alias.


303-308: LGTM!

The type-specific error messages clearly communicate completion requirements for different checklist types and align with the validation logic.


428-433: LGTM!

The type-specific button title provides clear user feedback that aligns with the validation requirements and error messaging.

packages/web/src/components/checklist/ROBINSIChecklist/SignallingQuestion.jsx (6)

1-1: LGTM!

The Show import is correctly added and used for conditional rendering of the optional label, following SolidJS best practices.


16-16: LGTM!

The JSDoc clearly documents the new isSkippable prop and its purpose.


21-29: LGTM!

The refined NA handling logic correctly coerces NA to NI only when NA is not a valid option for the question's response type, preserving NA when it's intentionally allowed.


31-38: Verify the toggle-to-deselect behavior is intentional.

The updated logic allows users to deselect an answer by clicking the same option again (sets to null). This differs from traditional radio button behavior where selection is permanent. Confirm this is the intended UX, particularly for optional/skippable questions.


48-50: LGTM!

The conditional opacity styling provides a clear visual indicator for skippable questions, complementing the "(Optional)" label.


59-61: LGTM!

The "(Optional)" label uses the Show component correctly per SolidJS guidelines and provides clear visual feedback for skippable questions.

Comment on lines +353 to 369
// Validate checklist completion based on checklist type
const isChecklistValid = createMemo(() => {
const type = checklistType();
const checklist = checklistForUI();
if (!checklist) return false;

if (type === 'AMSTAR2') {
return isAMSTAR2Complete(checklist);
}

// For non-AMSTAR2 checklists, allow completion (no validation)
if (type !== 'AMSTAR2') return true;
if (type === 'ROBINS_I') {
return isROBINSIComplete(checklist);
}

// For AMSTAR2, check if all questions have final answers
if (!checklist) return false;
return isAMSTAR2Complete(checklist);
// For other checklist types, allow completion
return true;
});
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 | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for checklist type definitions, enums, or constants
rg -n "type.*AMSTAR2|type.*ROBINS|type.*Generic|ChecklistType|CHECKLIST_TYPE" --type js --type jsx -B 2 -A 2 | head -80

Repository: InfinityBowman/corates

Length of output: 93


🏁 Script executed:

# Look for checklist type registrations and definitions
fd -e js -e jsx | xargs grep -l "checklist.*type\|getChecklistType\|checklistRegistry" | head -20

Repository: InfinityBowman/corates

Length of output: 1299


🏁 Script executed:

# Search for other completion validation functions
rg -n "isAMSTAR2Complete|isROBINSIComplete|isGenericComplete|isComplete" --type js --type jsx -B 1 -A 3

Repository: InfinityBowman/corates

Length of output: 93


🏁 Script executed:

# Check the checklist-registry for all registered types
fd checklist-registry -e js -e jsx | xargs cat

Repository: InfinityBowman/corates

Length of output: 48


🏁 Script executed:

cat packages/web/src/checklist-registry/types.js

Repository: InfinityBowman/corates

Length of output: 2544


🏁 Script executed:

cat packages/web/src/checklist-registry/index.js

Repository: InfinityBowman/corates

Length of output: 3733


🏁 Script executed:

cat packages/web/src/components/checklist/GenericChecklist.jsx

Repository: InfinityBowman/corates

Length of output: 2300


🏁 Script executed:

# Search for completion validation functions (corrected syntax)
rg "isAMSTAR2Complete|isROBINSIComplete|isGenericComplete|isComplete" --type js -B 1 -A 3

Repository: InfinityBowman/corates

Length of output: 17686


🏁 Script executed:

# Check what's in ChecklistYjsWrapper to understand the context better
sed -n '340,380p' packages/web/src/components/checklist/ChecklistYjsWrapper.jsx

Repository: InfinityBowman/corates

Length of output: 1248


Currently only AMSTAR2 and ROBINS_I are supported; the fallback behavior should be reconsidered for future extensibility.

The validation logic at lines 353-369 correctly handles the two registered checklist types (AMSTAR2 and ROBINS_I). However, the fallback case (line 368: return true) is a maintenance risk: if a new checklist type is added to CHECKLIST_REGISTRY in the future (as the comments in checklist-registry/types.js suggest for ROBINS_E, ROB2, GRADE), the validation would silently allow completion without applying type-specific validation logic.

Consider either:

  • Adding a console warning when an unregistered type is encountered, matching the pattern in getChecklistConfig() from the registry
  • Throwing an error for unknown types instead of assuming they're valid
  • Maintaining a checklist that any new type additions to the registry include corresponding validation logic
🤖 Prompt for AI Agents
In @packages/web/src/components/checklist/ChecklistYjsWrapper.jsx around lines
353 - 369, The current createMemo isChecklistValid uses a silent fallback
(return true) for unknown checklistType values, which will allow future
unhandled types to be marked complete; update the logic in isChecklistValid
(which reads checklistType() and checklistForUI()) to detect unknown types by
consulting the registry (e.g., call getChecklistConfig(checklistType()) or check
CHECKLIST_REGISTRY) and either log a warning with the type (console.warn or
process/logger) or throw an error instead of returning true, and ensure existing
branches still call isAMSTAR2Complete(checklist) and
isROBINSIComplete(checklist).

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.

Even smarter robins

2 participants