Skip to content

Fix GitBackend fs injection, diff hunks, and add signaling server#6

Merged
nsheaps merged 37 commits intomainfrom
claude/continue-work-yBYfQ
Mar 5, 2026
Merged

Fix GitBackend fs injection, diff hunks, and add signaling server#6
nsheaps merged 37 commits intomainfrom
claude/continue-work-yBYfQ

Conversation

@nsheaps
Copy link
Copy Markdown
Owner

@nsheaps nsheaps commented Mar 4, 2026

Summary

This PR addresses three key issues in the storage and signaling layers:

  1. Removes hardcoded node:fs dependency from GitBackend to support filesystem injection
  2. Implements proper unified diff hunk generation for file changes
  3. Adds a complete signaling server entry point with WebSocket support

Key Changes

GitBackend Filesystem Injection

  • Removed hardcoded import * as nodeFs from 'node:fs'
  • Added GitFs interface to define the filesystem contract expected by isomorphic-git
  • Modified constructor to accept fs: GitFs option, allowing injection of any compatible filesystem (node:fs, lightning-fs, memfs, etc.)
  • Updated all 30+ git operations to use this.fs instead of hardcoded nodeFs
  • Updated tests to pass fs: nodeFs explicitly

Diff Hunk Generation

  • Implemented generateUnifiedHunks() function using LCS (Longest Common Subsequence) algorithm
  • Implemented computeLcsDiff() to compute line-level diffs with context
  • Modified diff() method to populate actual hunks instead of empty arrays for:
    • Added files: shows new content with + prefix
    • Modified files: shows old/new content with -/+ prefixes and context lines
    • Deleted files: shows removed content with - prefix
  • Added hunk grouping with 3-line context around changes
  • Includes optimization for large files (>10k lines) with fallback to simple remove-all/add-all

Signaling Server Entry Point

  • Created packages/signaling-server/src/server.ts with Bun.serve() WebSocket listener
  • Integrated with existing RoomManager for room/connection management
  • Added /health endpoint for monitoring
  • Added /ws endpoint for WebSocket upgrades
  • Implemented connection tracking with WeakMap for memory efficiency
  • Added proper error handling and message parsing
  • Updated package.json with start script and bin entry point
  • Added @types/bun dev dependency

Implementation Details

  • The LCS diff algorithm handles up to 10k lines efficiently; larger files use a simpler strategy
  • Unified diff format includes proper hunk headers with line counts (@@ -old,count +new,count @@)
  • WebSocket connections are tracked by auto-incrementing IDs for logging and debugging
  • All git operations now support any filesystem implementation via dependency injection

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 4, 2026

Preview Deployment

The web app for this PR has been deployed:

Open Preview

Use this to verify the app works correctly, especially for dependency updates.

github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 4, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
@nsheaps nsheaps marked this pull request as ready for review March 5, 2026 03:43
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
github-actions bot added a commit that referenced this pull request Mar 5, 2026
…s, signaling entry point [P2.1]

- GitBackend now accepts an injected `fs` (GitFs interface) instead of
  hardcoding `import * as nodeFs from 'node:fs'`. All isomorphic-git calls
  use `this.fs` so BrowserFsBackend/lightning-fs can be passed in browser.
- diff() now generates real unified diff hunks by reading blob content at
  each commit and running an LCS-based line diff, instead of returning
  empty `hunks: []` arrays.
- Created signaling server entry point (src/server.ts) with Bun.serve()
  WebSocket listener wired to existing RoomManager, plus /health endpoint.
  Added `start` script and `bin` field to package.json.
- Added 3 new diff hunk tests verifying add/modify/delete produce content.

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
claude and others added 23 commits March 5, 2026 10:41
Implement create, switch, delete, and rename operations for
multiple workspaces. Each space stores its data under
.cept/spaces/{id}/ while the default space uses root paths
for backward compatibility. 13 unit tests.

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
…port [P2.10-P2.12]

Create ImportDialog component supporting both Notion ZIP import and
Obsidian vault import with progress indicators. Create ExportDialog
with format selection (Markdown/HTML/PDF) and browser download.
Both wire to existing core importer/exporter logic. 14 tests.

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
…sive E2E

- Wire SpaceManager into App.tsx with create/switch/delete/rename handlers
- Wire ImportDialog and ExportDialog into Settings and command palette
- Add deep linking via URL hash (page navigation updates hash, hash-based restore)
- Fix toggle block on tablets (touch-action, min-height 44px tap target)
- Add SettingsModal UI: Create Space form, Switch button, active badge, Import/Export section
- Add SettingsModal.test.tsx with 17 component tests
- Update roadmap.md: Phase 2 items marked Done, Phase 3/4 partial updates
- Update Playwright config: Desktop Chrome/Firefox, Mobile Chrome/Safari, Tablet (iPad)
- Add responsive.spec.ts: E2E tests for onboarding, sidebar, editor, settings, search,
  deep linking, import/export commands, and responsive screenshots
- Fix smoke.spec.ts to match actual landing page test IDs
- 1550 tests passing, lint + typecheck clean

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
Replace hash-based deep linking (#pageId) with proper path-based URLs:
  /s/{spaceId}/{pageId} — user space pages
  /docs/{pageId}        — documentation pages

- Add 404.html for GitHub Pages SPA routing (encodes path in ?route= param)
- Add Vite plugin to inject base path into 404.html at build time
- Create router.ts with parseRoute/buildPath/pushRoute/replaceRoute/restoreRoute
- Handle legacy hash URLs by converting to path routes on load
- Support back/forward navigation via popstate listener
- Works with both production (/) and preview (/cept/pr-N/) base paths
- 18 router unit tests, 1568 total tests passing

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
Production now deploys to nsheaps.github.io/cept/app/ instead of site
root. Both production and preview use the gh-pages branch pattern:

- Production: /cept/app/ (VITE_BASE_PATH=/cept/app/)
- Previews:   /cept/pr-N/ (VITE_BASE_PATH=/cept/pr-N/)

The site-level 404.html on gh-pages detects which app instance a URL
belongs to (app/ vs pr-N/) and redirects to that instance's index.html
with ?route= param, which the SPA router picks up via restoreRoute().

- release-web.yml: deploy to app/ subdir, generate site-level 404.html
  and root index.html redirect
- preview-deploy.yml: ensure site-level 404.html exists for previews
- router.ts: add setBasePath() for testability
- router.test.ts: add tests for /cept/app/ and /cept/pr-42/ base paths
- 1580 tests passing

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
The URL update effect was firing before the page tree was populated,
causing broken URLs on demo load and failed navigation on reload.

- Route restore now waits for pages to be populated (hasStarted + pages)
  instead of firing immediately on ready
- URL update effect guarded by both initializedRef and routeRestoredRef
  so it never fires during the initial render cascade
- Landing page never touches the URL (hasStarted guard)
- On reload: 404.html redirects with ?route=, app initializes, pages
  populate, then restore reads ?route= and navigates correctly
- On fresh visit + 'Try demo': restore runs after demo populates pages,
  finds no route to restore, then URL update kicks in normally

1580 tests passing
…h detection

- Add FileBrowser component for inspecting IndexedDB storage on tablet
  devices without dev tools (accessible from space settings)
- Add space switcher dropdown in sidebar header (click space name)
- Wire spaces/activeSpaceId/onSwitchSpace props to Sidebar from App
- Disable import buttons with "(coming soon)" labels
- Rework spaces tab with per-space switch and settings action buttons
- Fix router base path detection with runtime fallback from script src
  attributes when Vite's import.meta.env.BASE_URL is wrong

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
Sidebar changes:
- Move app menu from header to footer (Settings, Trash, New page)
- Settings button opens directly to spaces tab
- Remove inline trash management, add onOpenTrash for page view
- Remove emoji from search button, use SVG icons
- Add footer divider for visual separation

Page header changes:
- Move kebab menu (three dots) from right to left of title
- Page title now has input-box styling (white bg, border, rounded)
- Menu opens from left instead of right

Breadcrumbs:
- Remove emoji icons, show title text only

Content area:
- Add trash page view with restore/delete actions per item
- Improve empty state: "Select a page or start typing to create one"

All tests updated to match new structure.

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
…Move...

- Page title: remove always-visible border/outline, show only on hover
  (transparent border by default, white bg + border appears on hover)
- Remove selected/active background from Recent section items
  (selection highlight only shows in the Pages tree)
- Rename "Move to root" to "Move..." in sidebar context menu
- Add explicit white background to topbar/breadcrumbs header
- Make horizontal rules in editor content more subtle (lighter color)

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
…debar layout

- Move page actions kebab menu back to top-right of page header (was incorrectly on left)
- Style sidebar search button as white input box with border
- Revert HR color in editor back to #e5e7eb (was incorrectly changed to #f0f0f0)
- Move + New page button back to Pages section header (was in footer)
- Move Trash button above divider, Settings below divider in sidebar footer
- Remove white background from topbar header (was applied to wrong element)

https://claude.ai/code/session_01Daqq8quqH9qCt3r6f85Auq
- Remove duplicate H1s from demo content (PageHeader already shows title)
- Add AppMenu component to header bar (settings, help, about)
- Move sidebar Trash/Settings up (remove margin-top: auto from footer)
- Add Import from Notion/Obsidian to command palette
- Fix E2E tests: use page-title testid instead of editor H1, fix
  landing page selector, fix settings button testid
- Update unit tests for removed H1 content assertions

https://claude.ai/code/session_01WumaRCr4Yg2Yj18nvG2j7P

Co-authored-by: Claude <noreply@anthropic.com>
- Replace settings link in sidebar footer with vertical triple-dot menu
  containing Settings, Help & Docs, and About Cept links
- Remove page actions menu from PageHeader component (title editing remains)
- Repurpose AppMenu component as page actions menu (favorite, rename,
  duplicate, delete) positioned in the top-right header bar
- Update all unit tests and E2E tests for new menu locations

https://claude.ai/code/session_01T6ZUteigbLgngVR5NLETVH
1. Blank page on first click: delay editor render until content loads
   from backend (check undefined vs empty string)
2. Duplicate page shared children: clone content only, not child refs
3. Restore to wrong location: store parentId in trash, restore to
   original parent if it still exists
4. /checkbox creates horizontal rule: rename Task List to
   "To-do / Checkbox" so slash search matches correctly
5. Features page missing table: add table example to demo content
6. Space switcher can't switch to docs: add "Cept Docs" entry to
   space switcher dropdown
7. Docs directory pages not navigable: show FolderView with clickable
   child page links below docs editor
8. Cursor word underline: disable Link autolink and editor spellcheck
9. List item separator lines: add explicit border/decoration resets
   to list items and containers (Tailwind Preflight sets border-style
   solid on all elements)

https://claude.ai/code/session_01T6ZUteigbLgngVR5NLETVH
The docs space (cept-docs) was already in spaceInfoList via
DOCS_SPACE_INFO. Handle the existing id instead of adding a duplicate.

https://claude.ai/code/session_01T6ZUteigbLgngVR5NLETVH
- Add tiptap-markdown extension to CeptEditor for markdown I/O
- Store pages as .md files instead of .html (with legacy .html fallback)
- Convert demo content and docs content to markdown
- Remove mdToHtml converter from docs-content.ts (tiptap-markdown
  handles parsing natively)
- Disable file browser for docs space (read-only, no real backend)
- Update all editor tests to use markdown content
- Fix slash command test to match actual "To-do / Checkbox" title

https://claude.ai/code/session_01T6ZUteigbLgngVR5NLETVH
Lists all emoji icons used across the app: page icons, command palette,
and slash command menu items, organized by category with Unicode codepoints.

https://claude.ai/code/session_01Dw6Fi6JLngFjA3g5tQejDS
Three categories of failures:

1. Playwright config ran 5 browser projects (Chrome, Firefox, Safari,
   Mobile Safari, Tablet) but CI only installs Chromium. Restrict to
   Desktop Chrome + Mobile Chrome in CI; keep all 5 locally. Add 1
   retry in CI for flaky tests.

2. responsive.spec.ts used `getByText('Try the demo')` with an
   `if (isVisible())` guard that raced against page load — if the
   landing page hadn't rendered yet, the click was skipped and
   `.cept-editor` never appeared. Replace with a reliable helper that
   waits for the landing page, then clicks via `getByTestId('try-demo')`.

3. slash-commands.spec.ts `openDemoEditor` set localStorage to trigger
   demo mode via settings migration, which is fragile. Replace with
   the same click-the-button approach that the passing smoke tests use.

Also fix smoke tests for Mobile Chrome where the sidebar can cover the
editor on narrow viewports, and relax deep-linking assertions.

https://claude.ai/code/session_01MZtTcHgcL6CAimGwxEwQV9
The E2E job was gated to only run on main or non-draft PRs, which
prevented validating E2E fixes on feature branches. Remove the gate
so E2E tests run on every push and PR event.

https://claude.ai/code/session_01MZtTcHgcL6CAimGwxEwQV9
- On narrow viewports (<768px) the sidebar is position:fixed and covers
  the editor. After entering demo mode, close the sidebar so the
  `.cept-editor` assertion passes.
- Fix smoke test: use `landing-page not.toBeVisible` instead of the
  broken `.or().first()` chain (expect() doesn't have .first()).
- Fix "loads demo content" test: check for blockquote/callout since the
  demo content uses standard `>` blockquotes, not cept callout blocks.
- Fix search test: type "Search" to filter command palette instead of
  clicking a potentially unclickable `getByText('Search')` match.
- Fix deep linking test: use `getByTestId` for sidebar navigation.
- Open sidebar before tests that need it (App Menu, Sidebar Actions,
  demo page navigation) on mobile viewports.

https://claude.ai/code/session_01MZtTcHgcL6CAimGwxEwQV9
On mobile viewports (<768px), the sidebar opens by default with a fixed
backdrop (z-index 40) that covers the entire screen, preventing clicks
on landing page buttons. Added closeSidebarOnMobile() helper to all
three test files that dismisses the sidebar before interacting with
the landing page.

https://claude.ai/code/session_01MZtTcHgcL6CAimGwxEwQV9
The sidebar (z-index 50) covers the header toggle button on mobile,
making toggle.click() fail with "intercepts pointer events". Fixed by
clicking the sidebar backdrop (z-index 40) to the right of the 260px
sidebar instead.

https://claude.ai/code/session_01MZtTcHgcL6CAimGwxEwQV9
- Install release-it, @release-it/conventional-changelog, @release-it/bumper
- Add .release-it.json config based on nsheaps/ai-mktpl patterns
- Add release, release:ci, and release:dry-run scripts to package.json
- Add GitHub Actions release workflow with manual dispatch
  (supports major/minor/patch increment and dry-run option)

https://claude.ai/code/session_01EwbUn3GZiBFp36G5LrNiaB
…deploys

Inject __APP_VERSION__ (from package.json) and __COMMIT_SHA__ (from CI
env) at build time via Vite define. Preview and release workflows pass
COMMIT_SHA so deployed builds show the exact commit. The about page
displays "Version X.Y.Z (abc1234)" for CI builds and "Version X.Y.Z"
for local dev.

https://claude.ai/code/session_01EwbUn3GZiBFp36G5LrNiaB
github-actions bot added a commit that referenced this pull request Mar 5, 2026
@nsheaps nsheaps force-pushed the claude/continue-work-yBYfQ branch from 5d323d4 to f8d5f02 Compare March 5, 2026 15:41
github-actions bot added a commit that referenced this pull request Mar 5, 2026
@nsheaps nsheaps merged commit e3d3874 into main Mar 5, 2026
7 checks passed
@nsheaps nsheaps deleted the claude/continue-work-yBYfQ branch March 5, 2026 16:06
github-actions bot added a commit that referenced this pull request Mar 5, 2026
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.

2 participants