fix(stores): restore missing page header and clean up dead navigation code#100
Conversation
… code The page header (Share button, breadcrumbs, etc.) was missing from all pages because OptimizedViewHeader checked layoutStore.activePageId which was always null - the navigation system was designed but never wired up. Changes: - Fix OptimizedViewHeader to use useParams() instead of dead store state - Remove all dead navigation code from useLayoutStore (352→60 lines) - Remove duplicate sidebar state from useUIStore (97→50 lines) - Remove dead cleanup code from NavigationProvider.tsx - Remove dead sidebar hooks from useUI.ts (keep only useTreeState) - Update store tests to match new simplified state - Update state-management.md documentation The two stores now have clear, non-overlapping responsibilities: - useLayoutStore: sidebar open/closed state (persisted) - useUIStore: tree expansion and scroll state (persisted) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
WalkthroughThis PR shifts navigation responsibility to URL params, narrows layout store to sidebar visibility and rehydration, consolidates multiple UI hooks into a single tree-focused hook, and removes view caching, active page/drive tracking, and related lifecycle cleanup across components and debug tools. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (6)**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
apps/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
apps/web/src/**/*.tsx📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/{components,src/**/components}/**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
apps/web/src/**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧬 Code graph analysis (1)apps/web/src/components/layout/DebugPanel.tsx (1)
⏰ 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)
🔇 Additional comments (4)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/2.0-architecture/2.1-frontend/state-management.md (1)
482-509: Add language identifier to fenced code block.The code block illustrating the new architecture is missing a language identifier for syntax highlighting.
🔎 Proposed fix
-``` +```typescript ✅ CURRENT ARCHITECTURE:
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/web/src/components/layout/NavigationProvider.tsx(1 hunks)apps/web/src/components/layout/middle-content/CenterPanel.tsx(1 hunks)apps/web/src/hooks/useUI.ts(1 hunks)apps/web/src/stores/__tests__/useUIStore.test.ts(3 hunks)apps/web/src/stores/useLayoutStore.ts(1 hunks)apps/web/src/stores/useUIStore.ts(3 hunks)docs/2.0-architecture/2.1-frontend/state-management.md(14 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Never use
anytypes in TypeScript code - always use proper TypeScript types
**/*.{ts,tsx}: Noanytypes - always use proper TypeScript types
Use kebab-case for filenames (e.g.,image-processor.ts)
Use camelCase for variables and functions
Use UPPER_SNAKE_CASE for constants
Use PascalCase for types and enums
Use centralized permission logic: importgetUserAccessLevelandcanUserEditPagefrom@pagespace/lib/permissions
Use Drizzle client from@pagespace/dbfor all database access
Always structure message content using the message parts structure:{ parts: [{ type: 'text', text: '...' }] }
Use ESM modules and TypeScript strict mode
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/stores/useUIStore.tsapps/web/src/components/layout/NavigationProvider.tsxapps/web/src/hooks/useUI.tsapps/web/src/stores/useLayoutStore.tsapps/web/src/stores/__tests__/useUIStore.test.ts
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/**/*.{ts,tsx}: Use centralized permission functions from@pagespace/lib/permissionsfor access control, such asgetUserAccessLevel()andcanUserEditPage()
Always use Drizzle client from@pagespace/dbfor database access instead of direct database connections
Always use message parts structure withpartsarray containing objects withtypeandtextfields when constructing messages for AI
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/stores/useUIStore.tsapps/web/src/components/layout/NavigationProvider.tsxapps/web/src/hooks/useUI.tsapps/web/src/stores/useLayoutStore.tsapps/web/src/stores/__tests__/useUIStore.test.ts
apps/web/src/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/src/**/*.tsx: For document editing, register editing state usinguseEditingStore.getState().startEditing()andendEditing()to prevent unwanted UI refreshes
For AI streaming operations, register streaming state usinguseEditingStore.getState().startStreaming()andendStreaming()to prevent unwanted UI refreshes
When using SWR, checkuseEditingStorestate withisAnyActive()and setisPausedto prevent data refreshes during editing or streaming
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/components/layout/NavigationProvider.tsx
**/{components,src/**/components}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use PascalCase for React component names and filenames
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/components/layout/NavigationProvider.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Format code with Prettier and lint with ESLint using the configuration at
apps/web/eslint.config.mjs
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/stores/useUIStore.tsapps/web/src/components/layout/NavigationProvider.tsxapps/web/src/hooks/useUI.tsapps/web/src/stores/useLayoutStore.tsapps/web/src/stores/__tests__/useUIStore.test.ts
apps/web/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/web/src/**/*.{ts,tsx}: Use Zustand for client-side state management
Use SWR for server state and caching
Files:
apps/web/src/components/layout/middle-content/CenterPanel.tsxapps/web/src/stores/useUIStore.tsapps/web/src/components/layout/NavigationProvider.tsxapps/web/src/hooks/useUI.tsapps/web/src/stores/useLayoutStore.tsapps/web/src/stores/__tests__/useUIStore.test.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Tech stack: Next.js 15 App Router + TypeScript + Tailwind + shadcn/ui
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: Use Zustand for client state management and SWR for server state and caching
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use Zustand for client-side state management
📚 Learning: 2025-12-14T14:54:47.122Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Applies to **/*.{ts,tsx} : Use centralized permission logic: import `getUserAccessLevel` and `canUserEditPage` from `pagespace/lib/permissions`
Applied to files:
apps/web/src/components/layout/middle-content/CenterPanel.tsx
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: Applies to app/**/*.{ts,tsx} : Import and use `getUserAccessLevel()` and `canUserEditPage()` from `pagespace/lib/permissions` for centralized permission logic
Applied to files:
apps/web/src/components/layout/middle-content/CenterPanel.tsx
📚 Learning: 2025-12-14T14:54:15.319Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-14T14:54:15.319Z
Learning: Applies to apps/web/src/**/*.tsx : For AI streaming operations, register streaming state using `useEditingStore.getState().startStreaming()` and `endStreaming()` to prevent unwanted UI refreshes
Applied to files:
apps/web/src/stores/useUIStore.tsapps/web/src/hooks/useUI.tsapps/web/src/stores/__tests__/useUIStore.test.tsdocs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:15.319Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-14T14:54:15.319Z
Learning: Applies to apps/web/src/**/*.tsx : For document editing, register editing state using `useEditingStore.getState().startEditing()` and `endEditing()` to prevent unwanted UI refreshes
Applied to files:
apps/web/src/stores/useUIStore.tsapps/web/src/hooks/useUI.tsapps/web/src/stores/__tests__/useUIStore.test.tsdocs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:47.122Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use Zustand for client-side state management
Applied to files:
apps/web/src/stores/useUIStore.tsapps/web/src/hooks/useUI.tsapps/web/src/stores/useLayoutStore.tsdocs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:47.122Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Tech stack: Next.js 15 App Router + TypeScript + Tailwind + shadcn/ui
Applied to files:
apps/web/src/components/layout/NavigationProvider.tsxdocs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:45.713Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:45.713Z
Learning: Use Zustand for client state management and SWR for server state and caching
Applied to files:
apps/web/src/stores/useLayoutStore.tsdocs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:15.319Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-14T14:54:15.319Z
Learning: Applies to apps/web/src/**/*.tsx : When using SWR, check `useEditingStore` state with `isAnyActive()` and set `isPaused` to prevent data refreshes during editing or streaming
Applied to files:
docs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:47.122Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:47.122Z
Learning: Applies to apps/web/src/**/*.{ts,tsx} : Use SWR for server state and caching
Applied to files:
docs/2.0-architecture/2.1-frontend/state-management.md
📚 Learning: 2025-12-14T14:54:38.009Z
Learnt from: CR
Repo: 2witstudios/PageSpace PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T14:54:38.009Z
Learning: Applies to apps/web/app/**/{route,route.ts,route.js} : In Next.js 15, `params` in dynamic routes are Promise objects. You MUST await `context.params` before destructuring.
Applied to files:
docs/2.0-architecture/2.1-frontend/state-management.md
🧬 Code graph analysis (2)
apps/web/src/hooks/useUI.ts (1)
apps/web/src/stores/useUIStore.ts (1)
useUIStore(14-50)
apps/web/src/stores/__tests__/useUIStore.test.ts (1)
apps/web/src/stores/useUIStore.ts (1)
useUIStore(14-50)
🪛 markdownlint-cli2 (0.18.1)
docs/2.0-architecture/2.1-frontend/state-management.md
482-482: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ 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: Unit Tests
🔇 Additional comments (7)
docs/2.0-architecture/2.1-frontend/state-management.md (1)
78-95: LGTM: URL-based navigation pattern correctly documented.The documentation accurately reflects the architectural shift to URL-based navigation using Next.js App Router's
useParams()hook. This approach provides browser history support, shareable URLs, and eliminates the complexity of maintaining navigation state in Zustand.apps/web/src/stores/useLayoutStore.ts (1)
1-59: Excellent simplification with clear separation of concerns.The layout store has been successfully refactored from 352 lines to 60 lines (-83%), now focusing solely on sidebar visibility. The removal of navigation state (activePageId, navigateToPage, viewCache, etc.) aligns with the architectural decision to use URL-based navigation via Next.js App Router.
Key improvements:
- Clear single responsibility (sidebar state management)
- Proper persistence configuration (only sidebars, not rehydrated flag)
- Clean interface with minimal API surface
apps/web/src/components/layout/NavigationProvider.tsx (1)
21-58: LGTM: Clean removal of store-based navigation dependencies.The NavigationProvider has been properly simplified by removing:
- useLayoutStore dependency
- Unmount cleanup logic that saved navigation state
- layoutStore.clearCache() call in error boundary
This aligns with the architectural shift to URL-based navigation where the browser manages navigation state. The component's public API remains unchanged, ensuring backward compatibility.
apps/web/src/components/layout/middle-content/CenterPanel.tsx (1)
112-130: Critical fix: Header visibility now correctly derived from URL params.This change fixes the missing page header (Share button, breadcrumbs) issue by replacing the check for
layoutStore.activePageId(which was always null because store-based navigation was never wired up) withparams.pageIdfrom the URL.Root cause resolved:
- Before: Checked
layoutStore.activePageId→ always null → header never shown- After: Checks
params.pageIdfrom URL → correctly reflects current page → header shownThis follows Next.js 15 App Router best practices where the URL is the source of truth for navigation state.
apps/web/src/stores/__tests__/useUIStore.test.ts (1)
1-137: LGTM: Tests correctly updated to match focused UI store scope.The test suite has been appropriately refactored to test only the remaining functionality:
- Tree expansion state (Set of node IDs)
- Tree scroll position (number)
- State independence between these two concerns
Removed tests for deleted features (sidebars, navigation state) that are no longer part of the UI store. The remaining tests provide comprehensive coverage for tree state management.
apps/web/src/hooks/useUI.ts (1)
4-32: Excellent consolidation into a focused tree state hook.The refactoring from multiple discrete hooks to a single
useTreeStatehook is a significant improvement:Benefits:
- Clear, focused API for tree navigation state
- Proper memoization with
useCallbackto prevent unnecessary re-renders- Helper functions (
isExpanded,toggleExpanded) provide ergonomic access patterns- Reduced API surface (removed 5 hooks, added 1 focused hook)
Removed hooks were for deleted features:
useLeftSidebar,useRightSidebar→ sidebar state moved to layout storeuseCenterView,useNavigationState→ navigation moved to URL paramsuseResponsiveLayout→ no longer needed with simplified architectureapps/web/src/stores/useUIStore.ts (1)
1-50: LGTM: Focused tree state store with proper Set serialization.The UI store has been successfully simplified to manage only tree navigation state:
State:
treeExpanded: Set for expanded node IDstreeScrollPosition: number for scroll offsetPersistence handling (lines 38-47):
- Serialization: Converts Set → Array for localStorage
- Deserialization: Converts Array → Set with defensive fallback
- Properly excludes transient state from persistence
Removed features:
- Sidebar state → moved to layout store
- Navigation state → moved to URL params
- Center view type → removed (dead code)
The Set serialization logic is defensive and handles both Array and Set types during rehydration, providing robustness against data shape changes.
The layout store was simplified to only manage sidebar state, but DebugPanel and LayoutErrorBoundary still referenced the deleted clearCache() method and other removed properties (viewCache, activeDriveId, activePageId, centerViewType). These were all part of a navigation system that was designed but never wired up (dead code). The useful functionality is preserved: - Clear Cache button still clears localStorage/sessionStorage - Error boundary still clears storage on error 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
* feat(db): add activityLogs table for audit trail Add new database schema for enterprise activity monitoring: - New enums: activity_operation, activity_resource - New activityLogs table with: - User attribution with AI context (isAiGenerated, aiProvider, aiModel) - Full content snapshots for future rollback support - Hierarchical context (driveId, pageId) for filtering - Indexed for efficient queries by timestamp, user, drive, page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(lib): add activity logger service Add fire-and-forget activity logging functions: - logActivity(): Core logging function - logPageActivity(): Page CRUD operations - logPermissionActivity(): Permission changes - logDriveActivity(): Drive operations - logAgentConfigActivity(): Agent configuration changes Designed to never block user operations while maintaining comprehensive audit trail for enterprise compliance. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): add /api/activities endpoint Add context-aware activity fetching endpoint: - user context: User's own activity (dashboard view) - drive context: All drive activity (drive view) - page context: All page edits (page view) Includes permission checks (canUserViewPage, isUserDriveMember) and pagination support for large activity lists. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): replace Settings tab with Activity tab in sidebar - Add SidebarActivityTab component with context-aware activity display - Update right sidebar to use Activity tab instead of Settings - Update GlobalAssistantView to open Activity tab Activity tab features: - Search filtering - User avatars with AI indicator (Bot icon) - Operation icons (create, update, delete, etc.) - Relative timestamps - Loading skeletons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(store): update SidebarTab type from 'settings' to 'activity' Update usePageAgentDashboardStore and tests to use 'activity' tab instead of 'settings' to match new sidebar structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): inject activity logging into page CRUD routes Add logPageActivity calls to track: - Page creation (POST /api/pages) - Page updates (PATCH /api/pages/[pageId]) - Page deletion/trash (DELETE /api/pages/[pageId]) - Page restoration (POST /api/pages/[pageId]/restore) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): inject activity logging into permission routes Add logPermissionActivity calls to track: - Permission grants (POST /api/pages/[pageId]/permissions) - Permission updates (POST with existing permission) - Permission revocations (DELETE /api/pages/[pageId]/permissions) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): handle null values in activities query params Zod's .optional() and .default() only work with undefined, not null. searchParams.get() returns null for missing params, causing validation errors. Convert null → undefined with ?? operator. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ai): add activity logging to all AI tool operations AI tools now log to the activity system with full attribution: - Extended ToolExecutionContext with aiProvider, aiModel fields - Added logging to 11 write tools across 4 tool files - Pass AI context through experimental_context in 3 API routes - Export monitoring module from @pagespace/lib/server Tools now logged: replace_lines, create_page, rename_page, trash, restore, move_page, edit_sheet_cells, update_agent_config, update_task, create_drive, rename_drive 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR review comments - Wrap switch case declarations in blocks (/api/activities/route.ts) - Change driveId FK to 'set null' for audit trail preservation - Fix ProviderSetupCard to use inline mode instead of broken handler - Fix conversationId mapping to use session ID not page ID 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: fix mocks for activity logging functions Add missing mock functions for the new activity logging exports: - agent-tools.test.ts: add logAgentConfigActivity mock - page-write-tools.test.ts: add logPageActivity, logDriveActivity mocks - permissions/route.test.ts: add logPermissionActivity mock (moved to @pagespace/lib), add @pagespace/db mock for db.query.pages.findFirst All 2073 tests now pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: prefix unused provider param with underscore * Rewire iOS app after web refactor (#97) * fix(stores): restore missing page header and clean up dead navigation code (#100) * fix(stores): restore missing page header and clean up dead navigation code The page header (Share button, breadcrumbs, etc.) was missing from all pages because OptimizedViewHeader checked layoutStore.activePageId which was always null - the navigation system was designed but never wired up. Changes: - Fix OptimizedViewHeader to use useParams() instead of dead store state - Remove all dead navigation code from useLayoutStore (352→60 lines) - Remove duplicate sidebar state from useUIStore (97→50 lines) - Remove dead cleanup code from NavigationProvider.tsx - Remove dead sidebar hooks from useUI.ts (keep only useTreeState) - Update store tests to match new simplified state - Update state-management.md documentation The two stores now have clear, non-overlapping responsibilities: - useLayoutStore: sidebar open/closed state (persisted) - useUIStore: tree expansion and scroll state (persisted) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove references to deleted clearCache method in layout store The layout store was simplified to only manage sidebar state, but DebugPanel and LayoutErrorBoundary still referenced the deleted clearCache() method and other removed properties (viewCache, activeDriveId, activePageId, centerViewType). These were all part of a navigation system that was designed but never wired up (dead code). The useful functionality is preserved: - Clear Cache button still clears localStorage/sessionStorage - Error boundary still clears storage on error 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract URL state and agent conversation helpers (#101) * fix(stores): restore missing page header and clean up dead navigation code The page header (Share button, breadcrumbs, etc.) was missing from all pages because OptimizedViewHeader checked layoutStore.activePageId which was always null - the navigation system was designed but never wired up. Changes: - Fix OptimizedViewHeader to use useParams() instead of dead store state - Remove all dead navigation code from useLayoutStore (352→60 lines) - Remove duplicate sidebar state from useUIStore (97→50 lines) - Remove dead cleanup code from NavigationProvider.tsx - Remove dead sidebar hooks from useUI.ts (keep only useTreeState) - Update store tests to match new simplified state - Update state-management.md documentation The two stores now have clear, non-overlapping responsibilities: - useLayoutStore: sidebar open/closed state (persisted) - useUIStore: tree expansion and scroll state (persisted) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove references to deleted clearCache method in layout store The layout store was simplified to only manage sidebar state, but DebugPanel and LayoutErrorBoundary still referenced the deleted clearCache() method and other removed properties (viewCache, activeDriveId, activePageId, centerViewType). These were all part of a navigation system that was designed but never wired up (dead code). The useful functionality is preserved: - Clear Cache button still clears localStorage/sessionStorage - Error boundary still clears storage on error 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract URL state and agent conversation helpers - Add centralized url-state.ts for chat URL param management - Add shared agent-conversations.ts API helpers (DRY up fetch calls) - Add UI refresh protection (isPaused) to useBreadcrumbs, usePageTree, useConversations - Refactor usePageAgentDashboardStore and usePageAgentSidebarState to use shared helpers - Update state-management.md with AI assistant state boundaries documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR review comments from CodeRabbit - Fix stale isPaused closure in useBreadcrumbs, usePageTree, useConversations (use isEditingActive helper that reads live state via getState()) - Change 'push' to 'replace' when auto-loading most recent conversation - Add agentId/conversationId context to error messages for debugging - Update ui-refresh-protection.md docs with correct isPaused pattern - Add language identifier to code block in state-management.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * feat(db): add activityLogs table for audit trail Add new database schema for enterprise activity monitoring: - New enums: activity_operation, activity_resource - New activityLogs table with: - User attribution with AI context (isAiGenerated, aiProvider, aiModel) - Full content snapshots for future rollback support - Hierarchical context (driveId, pageId) for filtering - Indexed for efficient queries by timestamp, user, drive, page 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(lib): add activity logger service Add fire-and-forget activity logging functions: - logActivity(): Core logging function - logPageActivity(): Page CRUD operations - logPermissionActivity(): Permission changes - logDriveActivity(): Drive operations - logAgentConfigActivity(): Agent configuration changes Designed to never block user operations while maintaining comprehensive audit trail for enterprise compliance. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): add /api/activities endpoint Add context-aware activity fetching endpoint: - user context: User's own activity (dashboard view) - drive context: All drive activity (drive view) - page context: All page edits (page view) Includes permission checks (canUserViewPage, isUserDriveMember) and pagination support for large activity lists. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): replace Settings tab with Activity tab in sidebar - Add SidebarActivityTab component with context-aware activity display - Update right sidebar to use Activity tab instead of Settings - Update GlobalAssistantView to open Activity tab Activity tab features: - Search filtering - User avatars with AI indicator (Bot icon) - Operation icons (create, update, delete, etc.) - Relative timestamps - Loading skeletons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(store): update SidebarTab type from 'settings' to 'activity' Update usePageAgentDashboardStore and tests to use 'activity' tab instead of 'settings' to match new sidebar structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): inject activity logging into page CRUD routes Add logPageActivity calls to track: - Page creation (POST /api/pages) - Page updates (PATCH /api/pages/[pageId]) - Page deletion/trash (DELETE /api/pages/[pageId]) - Page restoration (POST /api/pages/[pageId]/restore) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(api): inject activity logging into permission routes Add logPermissionActivity calls to track: - Permission grants (POST /api/pages/[pageId]/permissions) - Permission updates (POST with existing permission) - Permission revocations (DELETE /api/pages/[pageId]/permissions) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): handle null values in activities query params Zod's .optional() and .default() only work with undefined, not null. searchParams.get() returns null for missing params, causing validation errors. Convert null → undefined with ?? operator. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ai): add activity logging to all AI tool operations AI tools now log to the activity system with full attribution: - Extended ToolExecutionContext with aiProvider, aiModel fields - Added logging to 11 write tools across 4 tool files - Pass AI context through experimental_context in 3 API routes - Export monitoring module from @pagespace/lib/server Tools now logged: replace_lines, create_page, rename_page, trash, restore, move_page, edit_sheet_cells, update_agent_config, update_task, create_drive, rename_drive 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR review comments - Wrap switch case declarations in blocks (/api/activities/route.ts) - Change driveId FK to 'set null' for audit trail preservation - Fix ProviderSetupCard to use inline mode instead of broken handler - Fix conversationId mapping to use session ID not page ID 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: fix mocks for activity logging functions Add missing mock functions for the new activity logging exports: - agent-tools.test.ts: add logAgentConfigActivity mock - page-write-tools.test.ts: add logPageActivity, logDriveActivity mocks - permissions/route.test.ts: add logPermissionActivity mock (moved to @pagespace/lib), add @pagespace/db mock for db.query.pages.findFirst All 2073 tests now pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: prefix unused provider param with underscore * refactor: replace ORM chain mocks with repository seams Create proper architectural boundaries for database operations: - Add pageRepository with 11 methods (findById, create, update, trash, etc.) - Add driveRepository with 5 methods (findById, findByIdBasic, etc.) - Add agentRepository with 2 methods (findById, updateConfig) Refactor AI tools to use repository seams: - agent-tools.ts now uses agentRepository - page-write-tools.ts now uses pageRepository + driveRepository Rewrite tests to mock repository boundaries: - agent-tools.test.ts: removed @scaffold label, 9 tests passing - page-write-tools.test.ts: removed @scaffold label, 23 tests passing Test scores improved from 6/10 to 9/10 per testing rubric. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): add missing isEditingActive export to usePageTree test mock The test mock for @/stores/useEditingStore was missing the isEditingActive named export that usePageTree.ts imports. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove unused db imports from page-write-tools Removed leftover imports (db, pages, drives, eq, and) that were replaced by repository seams in the refactor. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(test): add missing getActorInfo and logPageActivity mocks Added missing mocks for activity logging functions that were added to the API routes: - getActorInfo in @pagespace/lib/server mock - logPageActivity in @pagespace/lib mock Fixes 8 failing tests in pages route tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: implement fire-and-forget activity logging pattern Replace blocking `await getActorInfo()` calls with non-blocking helpers to avoid blocking user operations during activity logging: - Add logPageActivityAsync() for fire-and-forget page activity logging - Add logDriveActivityAsync() for fire-and-forget drive activity logging - Update all 9 logging call sites in page-write-tools.ts - Handle errors gracefully (still log activity even if actor lookup fails) - Use nullish coalescing for optional context fields - Fix TypeScript errors in test file with proper type assertions Addresses CodeRabbit review comment about blocking activity logging defeating the fire-and-forget design goal. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use null instead of undefined for parentId when moving to root Also add activity logging test assertions to verify logging is called after successful page operations (replace_lines, create_page, rename_page). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: prefix unused mockLogDriveActivity with underscore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Summary
OptimizedViewHeaderwas checkinglayoutStore.activePageIdwhich was always null because the navigation system was never wired upRoot Cause
The
useLayoutStorehad a complete navigation system designed (activePageId,navigateToPage(),hydrateFromUrl(), view caching) but it was never actually called. The app uses Next.jsuseParams()for navigation, making all this store state dead code.Additionally,
useUIStorehad duplicate sidebar state that was never used (actual sidebar state lives inuseLayoutStore).Changes
useLayoutStore.tsuseUIStore.tsuseUI.tsNavigationProvider.tsxCenterPanel.tsxuseParams()Store Responsibilities (After)
useLayoutStoreleftSidebarOpen,rightSidebarOpenuseUIStoretreeExpanded,treeScrollPositionTest plan
pnpm typecheck- passes🤖 Generated with Claude Code
Summary by CodeRabbit
Refactor
UI
Tests
Docs
✏️ Tip: You can customize this high-level summary in your review settings.