Skip to content

refactor: decouple useCollaborationStatus from lint WebSocket endpoint#154

Open
R-Hart80 wants to merge 9 commits intoCatholicOS:devfrom
R-Hart80:refactor/decouple-collaboration-status
Open

refactor: decouple useCollaborationStatus from lint WebSocket endpoint#154
R-Hart80 wants to merge 9 commits intoCatholicOS:devfrom
R-Hart80:refactor/decouple-collaboration-status

Conversation

@R-Hart80
Copy link
Copy Markdown
Contributor

@R-Hart80 R-Hart80 commented Apr 15, 2026

Closes #140

Summary

  • useCollaborationStatus: removed all WebSocket logic — returns "disabled" state until the real /collab/ws endpoint is implemented
  • HealthCheckPanel: added onWsStatusChange prop to expose the lint WS connection state to the parent
  • DeveloperEditorLayout: threads onLintWsStatusChange prop down to HealthCheckPanel
  • Editor toolbar: collab icon now uses useCollaborationStatus; lint icon uses HealthCheckPanel WS status and only renders when the panel is open (eliminating the duplicate connection)
  • Viewer toolbar: removed lint WS icon — the viewer has no HealthCheckPanel
  • Removed connectionStatus / wsEndpoint / wsPurpose from useProjectViewer return value
  • Removed stale "exposes collaboration status" test from useProjectViewer tests

Before / After

Before:

Editor toolbar:
  [collab icon: disabled hardcoded]  [lint icon: useCollaborationStatus → /lint/ws]
HealthCheckPanel: creates its own WebSocket → /lint/ws  ← duplicate connection

After:

Editor toolbar:
  [collab icon: useCollaborationStatus → disabled]  [lint icon: HealthCheckPanel WS, only when open]
HealthCheckPanel: single WebSocket → /lint/ws, exposes status via onWsStatusChange

Test plan

  • Open editor — collab icon shows as disabled; no lint icon visible when health check panel is closed
  • Open health check panel — lint WS icon appears and shows connecting → connected
  • Close health check panel — lint WS icon disappears
  • Viewer page — only collab (disabled) icon visible, no lint icon

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Collaboration support simplified: real-time collaboration is shown as disabled/"coming soon".
  • UI

    • Project header displays a disabled collaboration status indicator.
    • Editor (developer mode) shows a separate lint WebSocket status in the Health Check panel; that panel resets lint status when closed and reports connection progress.
  • Tests

    • Removed a unit test that asserted collaboration connection status exposure.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Decouples lint WebSocket handling from collaboration presence: useCollaborationStatus is stubbed to a disabled collab endpoint, HealthCheckPanel exclusively manages the lint WS and reports its status via a callback wired through DeveloperEditorLayout to editor pages; useProjectViewer no longer exposes WS-related fields.

Changes

Cohort / File(s) Summary
Tests
__tests__/lib/hooks/useProjectViewer.test.ts
Removed a unit test asserting useProjectViewer exposes collaboration/WebSocket fields.
Collaboration hook
lib/hooks/useCollaborationStatus.ts
Replaced active lint-WS lifecycle with a disabled stub: returns status: "disabled", isConnected: false, endpoint: "/api/v1/collab/ws", purpose: "Real-time collaboration (coming soon)"; simplified signature/options; removed reconnect logic.
Project viewer hook
lib/hooks/useProjectViewer.ts
Removed collaboration/WebSocket fields from public return shape (connectionStatus, wsEndpoint, wsPurpose) and related wiring.
Health check panel
components/editor/HealthCheckPanel.tsx
Added optional onWsStatusChange prop; emit connecting/connected/disconnected across WS lifecycle and cleanup; updated effect dependencies and guard to create socket only when effect still active.
Developer layout
components/editor/developer/DeveloperEditorLayout.tsx
Added props showHealthCheck, onCloseHealthCheck, and onLintWsStatusChange?; conditionally mounts HealthCheckPanel and forwards lint WS status callback.
Editor pages
app/projects/[id]/editor/page.tsx, app/projects/[id]/page.tsx
Editor pages now use useCollaborationStatus for collab icon (stub) and local lintWsStatus for lint WS icon; show lint WS ConnectionStatus only when HealthCheckPanel is open and wire health-check visibility/state to DeveloperEditorLayout.

Sequence Diagram(s)

sequenceDiagram
  participant EditorPage
  participant useCollab as useCollaborationStatus
  participant DevLayout as DeveloperEditorLayout
  participant HealthPanel as HealthCheckPanel
  participant LintWS as Lint WS

  EditorPage->>useCollab: request collaboration status (projectId)
  useCollab-->>EditorPage: status="disabled", endpoint="/api/v1/collab/ws"
  EditorPage->>DevLayout: render with showHealthCheck/onClose/onLintWsStatusChange
  DevLayout->>HealthPanel: mount when showHealthCheck=true (pass onWsStatusChange)
  HealthPanel->>LintWS: open WS when mounted
  LintWS-->>HealthPanel: open / message / close / error events
  HealthPanel-->>DevLayout: onWsStatusChange("connecting"/"connected"/"disconnected")
  DevLayout-->>EditorPage: propagate lint WS status via callback/state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • damienriehl

Poem

🐰 I hopped through tangled webs of code,
I nudged the lint to mind its road.
Collab is sleeping, endpoints clear,
Panels whisper status when you peer. 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main refactoring effort: decoupling useCollaborationStatus from the lint WebSocket endpoint, which is the central objective of this changeset.
Linked Issues check ✅ Passed All objectives from #140 are met: useCollaborationStatus now returns disabled/collab endpoint, lint WS centralized in HealthCheckPanel, HealthCheckPanel exposes status via callback, editor toolbar shows separate collab and lint icons, and duplicate hardcoded icon removed.
Out of Scope Changes check ✅ Passed All changes directly support the decoupling objective. Removed test case and useProjectViewer cleanup are necessary scope adjustments; page-level HealthCheckPanel guard ensures single connection in developer mode.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/projects/`[id]/editor/page.tsx:
- Around line 911-917: The ConnectionStatus lint indicator is currently gated by
showHealthCheck but HealthCheckPanel may not be mounted, causing a misleading
disconnected icon; change the render condition to the actual panel
mount/visibility flag used for HealthCheckPanel (e.g., isHealthCheckPanelOpen,
healthCheckPanelMounted, or whatever state/prop controls mounting of
HealthCheckPanel) so ConnectionStatus is only rendered when the panel (and its
WS) exists; keep the same props (state={lintWsStatus} and endpoint using
projectId) but replace showHealthCheck with the true panel visibility/mount
variable referenced where HealthCheckPanel is rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 984e75c7-b4ae-43f1-a1b9-45946bf8e8fc

📥 Commits

Reviewing files that changed from the base of the PR and between a412ed7 and 1ed563f.

📒 Files selected for processing (7)
  • __tests__/lib/hooks/useProjectViewer.test.ts
  • app/projects/[id]/editor/page.tsx
  • app/projects/[id]/page.tsx
  • components/editor/HealthCheckPanel.tsx
  • components/editor/developer/DeveloperEditorLayout.tsx
  • lib/hooks/useCollaborationStatus.ts
  • lib/hooks/useProjectViewer.ts
💤 Files with no reviewable changes (3)
  • tests/lib/hooks/useProjectViewer.test.ts
  • app/projects/[id]/page.tsx
  • lib/hooks/useProjectViewer.ts

Comment thread app/projects/[id]/editor/page.tsx
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/projects/`[id]/editor/page.tsx:
- Line 93: The lintWsStatus state can persist across panel unmounts causing
stale “connected” UI; add logic to reset it to "disconnected" whenever the
health-check panel is hidden or developer mode is turned off: update the
component containing lintWsStatus and setLintWsStatus to include a useEffect
that watches showHealthCheck and developerMode (or whatever prop/state controls
developer mode) and calls setLintWsStatus("disconnected") when showHealthCheck
becomes false or developerMode is false; if there is a dedicated health-check
panel component with a useEffect for mount/unmount (or a cleanup callback in the
WS connection handler), ensure that on unmount you also call
setLintWsStatus("disconnected") to clear state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 94340e4c-b12b-4cf0-9e0e-1b01fb8a9c20

📥 Commits

Reviewing files that changed from the base of the PR and between 1ed563f and 7adba1c.

📒 Files selected for processing (1)
  • app/projects/[id]/editor/page.tsx

Comment thread app/projects/[id]/editor/page.tsx
@JohnRDOrazio JohnRDOrazio added the enhancement New feature or request label Apr 20, 2026
R-Hart80 and others added 3 commits April 28, 2026 11:39
Closes CatholicOS#140. Previously useCollaborationStatus connected to /lint/ws as a
placeholder, creating a duplicate WebSocket connection alongside HealthCheckPanel.

Changes:
- useCollaborationStatus: removed WebSocket logic, returns "disabled" state
  until the real /collab/ws endpoint is available
- HealthCheckPanel: added onWsStatusChange prop to expose lint WS status
- DeveloperEditorLayout: threads onLintWsStatusChange down to HealthCheckPanel
- Editor toolbar: collab icon uses useCollaborationStatus; lint icon uses
  HealthCheckPanel WS status and only renders when the panel is open
- Viewer toolbar: removed lint WS icon (no HealthCheckPanel in viewer)
- Removed connectionStatus/wsEndpoint/wsPurpose from useProjectViewer return
- Removed stale "exposes collaboration status" test from useProjectViewer tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…unt condition

CodeRabbit noted that showHealthCheck alone is insufficient — HealthCheckPanel
is only mounted inside DeveloperEditorLayout (developer mode). Added
editorMode === "developer" to the lint ConnectionStatus condition so the icon
only appears when the panel is actually mounted and the WebSocket is active.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CodeRabbit noted that lintWsStatus could remain stale when the panel closes
before the WebSocket cleanup callback fires. Added a useEffect that resets the
state to "disconnected" whenever showHealthCheck is false or editorMode is not
"developer", ensuring the UI is never stuck in a connected state after the panel
and its WebSocket are gone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@R-Hart80 R-Hart80 force-pushed the refactor/decouple-collaboration-status branch from 1545871 to 7c223ca Compare April 28, 2026 14:44
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/projects/`[id]/editor/page.tsx:
- Around line 1066-1069: The page currently mounts a second HealthCheckPanel
causing duplicate WebSocket connections; update the page-level HealthCheckPanel
usage so it is not mounted in developer mode (guard its render with editorMode
!== "developer") or remove it entirely and rely on DeveloperEditorLayout's
HealthCheckPanel which already reports status via
onLintWsStatusChange/setLintWsStatus; target the HealthCheckPanel render and
props (showHealthCheck, onCloseHealthCheck, onLintWsStatusChange,
onUpdateProperty) and ensure only DeveloperEditorLayout keeps the WS-handling
HealthCheckPanel to avoid parallel connections.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2b2b50bb-0372-46f5-890e-3d9241b0a8a0

📥 Commits

Reviewing files that changed from the base of the PR and between 1545871 and 7c223ca.

📒 Files selected for processing (7)
  • __tests__/lib/hooks/useProjectViewer.test.ts
  • app/projects/[id]/editor/page.tsx
  • app/projects/[id]/page.tsx
  • components/editor/HealthCheckPanel.tsx
  • components/editor/developer/DeveloperEditorLayout.tsx
  • lib/hooks/useCollaborationStatus.ts
  • lib/hooks/useProjectViewer.ts
💤 Files with no reviewable changes (2)
  • tests/lib/hooks/useProjectViewer.test.ts
  • lib/hooks/useProjectViewer.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/projects/[id]/page.tsx
  • components/editor/developer/DeveloperEditorLayout.tsx
  • components/editor/HealthCheckPanel.tsx

Comment thread app/projects/[id]/editor/page.tsx
In developer mode, DeveloperEditorLayout already mounts HealthCheckPanel
and reports its WS status via onLintWsStatusChange. Mounting a second
panel in the page caused duplicate WebSocket connections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/projects/[id]/editor/page.tsx (1)

69-75: ⚠️ Potential issue | 🟡 Minor

Remove the unused enableWebSocket parameter—it's never referenced in the hook implementation.

The parameter is defined in the interface and destructured in the function signature, but never used in the function body or return statement. Since WebSocket connections for lint status and quality checks are managed independently by HealthCheckPanel and other components (not by useProjectViewer), this parameter is dead code and should be removed along with its JSDoc comment. The decoupling from websocket lifecycle is already complete.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/projects/`[id]/editor/page.tsx around lines 69 - 75, Remove the dead
enableWebSocket option from the useProjectViewer API: delete the enableWebSocket
property from the hook's options interface and JSDoc, remove it from the
useProjectViewer function parameter destructuring/signature and any internal
references, and update all call sites (e.g., the call in page.tsx that passes
enableWebSocket: true) to stop passing that option; leave WebSocket lifecycle to
HealthCheckPanel and other components as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/projects/`[id]/editor/page.tsx:
- Around line 916-927: The toolbar currently shows the lint ConnectionStatus
only when showHealthCheck && editorMode === "developer"; instead, wire the
page-level HealthCheckPanel to publish lint WebSocket status by passing the
setter (setLintWsStatus) into that component (the HealthCheckPanel instance that
currently mounts elsewhere) and change the toolbar branch to render the lint
ConnectionStatus whenever showHealthCheck is true (remove the editorMode ===
"developer" guard) using state={lintWsStatus}, purpose="Real-time lint status
updates" and endpoint={`/api/v1/projects/${projectId}/lint/ws`} so the icon
follows the open HealthCheckPanel across both modes.

---

Outside diff comments:
In `@app/projects/`[id]/editor/page.tsx:
- Around line 69-75: Remove the dead enableWebSocket option from the
useProjectViewer API: delete the enableWebSocket property from the hook's
options interface and JSDoc, remove it from the useProjectViewer function
parameter destructuring/signature and any internal references, and update all
call sites (e.g., the call in page.tsx that passes enableWebSocket: true) to
stop passing that option; leave WebSocket lifecycle to HealthCheckPanel and
other components as-is.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee9ed195-97f8-4f67-869c-3bb0b8f35d9b

📥 Commits

Reviewing files that changed from the base of the PR and between 7c223ca and 2271a14.

📒 Files selected for processing (1)
  • app/projects/[id]/editor/page.tsx

Comment thread app/projects/[id]/editor/page.tsx
R-Hart80 and others added 2 commits April 28, 2026 13:09
- Add missing ConnectionStatus import to page.tsx (viewer)
- Add missing HealthCheckPanel import to DeveloperEditorLayout
- Add canManage prop to DeveloperEditorLayoutProps and pass it from editor page
- Make showHealthCheck/onCloseHealthCheck optional (viewer and tests don't use them)
- Remove enableWebSocket from UseProjectViewerOptions (no longer used after stub)
- Remove enableWebSocket: true call-site in editor page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update useCollaborationStatus tests to match stub behavior
- Add addEventListener to createLintWebSocket mock (beforeEach and initial)
- Remove fetchData from WS effect deps (fetchDataRef already used inside)
- Pass setLintWsStatus to page-level HealthCheckPanel (standard mode)
- Show lint ConnectionStatus whenever panel is open, not just in developer mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 11 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
components/editor/HealthCheckPanel.tsx 43.75% 6 Missing and 3 partials ⚠️
...ponents/editor/developer/DeveloperEditorLayout.tsx 60.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

R-Hart80 and others added 3 commits April 28, 2026 16:20
The mockImplementation at the lint_started/lint_complete test was
returning a WebSocket stub without addEventListener, causing an
unhandled error when the component called ws.addEventListener().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds unit tests for the onWsStatusChange status transitions
(disconnected/connecting/connected/cleanup) in HealthCheckPanel and
verifies that DeveloperEditorLayout renders HealthCheckPanel only when
showHealthCheck is true, closing the Codecov patch gap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TypeScript 5.x narrows let variables assigned inside closures to never.
Using a { fn } object holder avoids this — object property access is not
subject to closure-based control flow narrowing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: decouple useCollaborationStatus from lint WebSocket endpoint

2 participants