Skip to content

feat(rooms): true sibling-room isolation (Rooms v3) - #99

Merged
hilash merged 1 commit into
mainfrom
feat/rooms-v3-isolation
May 23, 2026
Merged

feat(rooms): true sibling-room isolation (Rooms v3)#99
hilash merged 1 commit into
mainfrom
feat/rooms-v3-isolation

Conversation

@hilash

@hilash hilash commented May 23, 2026

Copy link
Copy Markdown
Collaborator

Rooms v3 — true sibling-room isolation

Makes data/ a neutral home container and every room a self-contained, isolated sibling cabinet (data/<room>/). No room is the parent of another, so Personal and Work never mix. This reverses v2's "root is the default room" direction, where the root cabinet was simultaneously a room and the physical parent of every other room (isolation could only be faked with a UI filter).

What changed

  • Room model: listRooms() returns only top-level dirs with a .cabinet, excluding the home; plain folders are no longer shown as rooms. /api/rooms returns defaultRoom from data/.home/home.json, and the app lands inside the default room (the logo home button is the switcher).
  • Creation: "Add room" makes an isolated top-level room (kind:room + auto icon/color); the sidebar "New Cabinet" nests inside the current room (kind:child).
  • Isolation: the tree is rooted per room; per-room search (each room has its own .cabinet.db; pages/agents/tasks scoped by room prefix, cabinet param threaded palette → API → daemon); roll-up never crosses a room boundary (the home rolls up nothing); switching rooms clears the stale selected page.
  • Identity/theme: each room stores icon + color + theme in its .cabinet; RoomThemeSync applies the room theme on switch and on load, with global fallback (verified live).
  • Multi-window: "Open in new window" opens a window scoped to the room — Electron spawns a native BrowserWindow reusing the backend (cabinet:open-window IPC + CabinetDesktop.openWindow), web uses window.open. Each window keeps its own room + theme.
  • Onboarding: scaffolds the first room at data/<slug>/ and writes the home marker; global app config stays at the container (data/.agents/.config).
  • Migration: scripts/migrate-rooms-v3.mjs for existing installs — idempotent and git-checkpointed.

Note

Kept a thin kind:home data/.cabinet so the ~114 "."-as-root call sites resolve to a valid but empty (leak-free) scope, instead of a full retire-. refactor.

Verification

Model, isolation, theme-on-switch, multi-window, and from-scratch onboarding were all verified via Chrome DevTools + filesystem inspection (see PROGRESS.md, 2026-05-23).

Docs

  • docs/ROOMS_WORKSPACES_PRD.md updated to shipped v3.
  • Adds docs/ROOMS_V3_TRUE_ISOLATION_PLAN.md (gap analysis + migration spec).

Summary by CodeRabbit

  • New Features

    • Rooms are now structurally isolated with independent data directories and search indices.
    • Home container serves as a neutral starting point with configurable default room selection.
    • Room switcher clears prior state when switching between rooms.
    • Search results are scoped to the active room.
  • Chores

    • Added migration script to restructure existing workspaces to new room layout.
    • Updated .gitignore to exclude backup directories.

Review Change Stack

Make data/ a neutral "home" container and every room a self-contained,
isolated sibling cabinet (data/<room>/). No room is the parent of another,
so Personal and Work never mix. Reverses v2's "root is the default room"
direction, which made the root cabinet both a room and the parent of all
rooms (isolation could only be faked with a UI filter).

- listRooms: only top-level dirs with a .cabinet, excluding the home;
  plain folders are no longer shown as rooms
- /api/rooms returns defaultRoom from data/.home/home.json; the app lands
  inside the default room (the logo home button is the room switcher)
- creation: "Add room" makes an isolated top-level room (kind:room + auto
  icon/color); the sidebar "New Cabinet" nests inside the current room
- per-room search: each room has its own .cabinet.db; pages/agents/tasks
  scoped by room prefix (cabinet param threaded palette -> API -> daemon)
- roll-up never crosses a room boundary (the home rolls up nothing)
- switching rooms clears the stale selected page
- onboarding scaffolds the first room at data/<slug>/ and writes the home
  marker; global app config stays at the container (data/.agents/.config)
- migration for existing installs: scripts/migrate-rooms-v3.mjs
  (idempotent, git-checkpointed)
- verified per-room theme-on-switch (RoomThemeSync) and multi-window
  "open in new window" (Electron cabinet:open-window IPC + web window.open)

Kept a thin kind:home data/.cabinet so the ~114 "."-as-root call sites
resolve to a valid but empty (leak-free) scope instead of a full retire-"."
refactor.

Docs: ROOMS_WORKSPACES_PRD.md updated to shipped v3; adds
ROOMS_V3_TRUE_ISOLATION_PLAN.md (gap analysis + migration spec).
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b01edfb6-5443-4a55-8765-f3164b37ac2b

📥 Commits

Reviewing files that changed from the base of the PR and between 271df4b and e3a2bf0.

📒 Files selected for processing (20)
  • .gitignore
  • PROGRESS.md
  • docs/ROOMS_V3_TRUE_ISOLATION_PLAN.md
  • docs/ROOMS_WORKSPACES_PRD.md
  • scripts/migrate-rooms-v3.mjs
  • server/cabinet-daemon.ts
  • server/search/index-agents-tasks.ts
  • server/search/search-service.ts
  • src/app/api/cabinets/create/route.ts
  • src/app/api/onboarding/setup/route.ts
  • src/app/api/rooms/route.ts
  • src/app/api/search/route.ts
  • src/components/layout/app-shell.tsx
  • src/components/search/search-palette.tsx
  • src/components/sidebar/room-switcher.tsx
  • src/components/sidebar/sidebar.tsx
  • src/lib/cabinets/overview.ts
  • src/lib/cabinets/rooms.ts
  • src/lib/storage/cabinet-scaffold.ts
  • src/stores/rooms-store.ts

📝 Walkthrough

Walkthrough

This PR implements Rooms v3, restructuring the Cabinet app from a root-cabinet model to true sibling room isolation. Each room becomes an independent cabinet at data/<slug>/ with its own .cabinet manifest, database, and agents/chat directories, while data/ becomes a neutral home container. An idempotent migration script transforms existing layouts, and search/listing/navigation are updated to enforce per-room scoping.

Changes

Rooms v3 True Sibling Isolation

Layer / File(s) Summary
Design specification and migration plan
docs/ROOMS_V3_TRUE_ISOLATION_PLAN.md, docs/ROOMS_WORKSPACES_PRD.md, PROGRESS.md, .gitignore
New v3 design doc defines structural model with data/ as home container and rooms as top-level cabinet siblings; v2 PRD updated to mark v3 as shipped with concrete filesystem layout and idempotent migration; progress log records decision and verification; backup ignore patterns added.
Core room discovery and home container support
src/lib/cabinets/rooms.ts, src/lib/cabinets/overview.ts, src/lib/storage/cabinet-scaffold.ts
listRooms() rewrites to return only manifested top-level directories excluding home; new HomeConfig/getHomeConfig()/resolveDefaultRoom() functions manage persistent default-room selection; overview prevents home from rolling up descendants; scaffold options expanded to include room/home kinds.
Idempotent migration CLI
scripts/migrate-rooms-v3.mjs
New script detects prior migration state, moves existing root cabinet into data/<slug>/, preserves top-level cabinets as siblings with backfilled identity, splits .agents/.config into room and container scopes, writes home manifest and data/.home/home.json.
Search room-scoped filtering
server/search/search-service.ts, server/search/index-agents-tasks.ts, server/cabinet-daemon.ts, src/app/api/search/route.ts
AgentDoc/TaskDoc add optional cabinet field; runSearch() accepts cabinet param and filters results by room membership; index loaders compute cabinet from filesystem paths; daemon and API routes accept and forward cabinet query parameter.
Room API endpoints and state management
src/app/api/rooms/route.ts, src/stores/rooms-store.ts
GET /api/rooms returns both rooms list and resolved defaultRoom; rooms store adds defaultRoom state and fetches both fields from API response.
Room-scoped onboarding and cabinet creation
src/app/api/onboarding/setup/route.ts, src/app/api/cabinets/create/route.ts
Onboarding scaffolds first room under data/<roomSlug>/, writes home container manifest and default-room config, moves agents/chat into room scope; cabinet creation assigns kind: "room" to top-level and kind: "child" to nested, with best-effort icon/color metadata.
UI navigation, search scoping, and room switching
src/components/layout/app-shell.tsx, src/components/search/search-palette.tsx, src/components/sidebar/room-switcher.tsx, src/components/sidebar/sidebar.tsx
AppShell loads rooms on mount and redirects bare home to default room; SearchPalette scopes search by active room cabinet; RoomSwitcher clears tree/editor state on switch; Sidebar derives parentPath from current room for new-cabinet dialog.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • hilash/cabinet#84: Both PRs extend cabinet scaffolding and onboarding routes; this PR restructures room/home layout while that PR adds locale forwarding through the same pathway.

🐰 A burrow once nested deep with rooms in all directions,
Now each has its own hidden chamber, true isolation perfection!
No more do the walls blur—each space distinct and free,
Home's a neutral ground, where wanderers can be. 🏡✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rooms-v3-isolation

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.

@hilash
hilash merged commit affbb5f into main May 23, 2026
1 check was pending
@hilash
hilash deleted the feat/rooms-v3-isolation branch May 23, 2026 16:04
XcluEzy7 pushed a commit to XcluEzy7/cabinet that referenced this pull request May 27, 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.

1 participant