Skip to content

Refactor web stores into atomic slices#1708

Open
justsomelegs wants to merge 2 commits intopingdotgg:mainfrom
justsomelegs:web/atomic-store-refactor
Open

Refactor web stores into atomic slices#1708
justsomelegs wants to merge 2 commits intopingdotgg:mainfrom
justsomelegs:web/atomic-store-refactor

Conversation

@justsomelegs
Copy link
Copy Markdown

@justsomelegs justsomelegs commented Apr 3, 2026

What Changed

Refactored the web orchestration store from broad array-based state into a more atomic normalized shape.

Main changes:

  • replaces projects[] / threads[] as the primary store shape with keyed records and id lists
  • splits thread state into narrower slices instead of storing one large thread object as the main reactive unit
  • updates web consumers to read direct keyed state instead of subscribing to large collections and scanning them
  • updates the web test suite and fixtures to use the new normalized store model

Old Pattern

const threads = useStore((s) => s.threads);
const activeThread = threads.find((thread) => thread.id === threadId);
const messages = activeThread?.messages ?? [];

const project = useStore((s) =>
  s.projects.find((project) => project.id === projectId)
);

New Pattern

const shell = useStore((s) => s.threadShellById[threadId]);
const session = useStore((s) => s.threadSessionById[threadId] ?? null);
const messageIds = useStore((s) => s.messageIdsByThreadId[threadId] ?? EMPTY_IDS);

const project = useStore((s) => s.projectById[projectId]);

Why

The old store shape forced many consumers to read broad collections and then search inside them. That made fine-grained subscriptions hard and set us up for unnecessary rerenders once we start breaking large components into smaller ones.

This change establishes the state model we actually want to build on:

  • direct keyed access for exact reads
  • smaller reactive boundaries inside thread state
  • a cleaner base for future work on Sidebar, ChatView, and other hot UI paths

Keeping this as a store-shape-first PR also keeps the follow-up performance work simpler. Future PRs can focus on splitting components and wiring each subcomponent to only the exact slice it needs.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Refactor web store state from denormalized arrays to normalized id/map slices

  • Replaces projects, threads, and sidebarThreadsById arrays in AppState with normalized maps (projectById, threadShellById, threadSessionById, threadTurnStateById, per-thread message/activity/plan/diff maps) and corresponding id arrays.
  • Adds writeThreadState and removeThreadState as central writers that atomically update all normalized slices, handling project moves and sidebar summary maintenance.
  • Adds selectProjects and selectThreads selectors to hydrate full entity arrays from normalized state; existing selectProjectById and selectThreadById are reimplemented against the new maps.
  • Introduces createThreadSelector in storeSelectors.ts, a memoized selector factory that assembles a full Thread from state shards and returns stable references when inputs are unchanged.
  • All consumers (components, hooks, tests) are updated to read from normalized maps and use the new selectors instead of scanning arrays.
  • Behavioral Change: any code reading state.projects, state.threads, or state.sidebarThreadsById directly will break; all reads must go through selectors or normalized maps.

Macroscope summarized 0737ff4.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f8da93c9-4a92-48ad-9168-6d2d3e02f71d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ 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.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 3, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 3, 2026

Approvability

Verdict: Needs human review

This is a major architectural refactor of the central state management store, converting from nested arrays to normalized atomic slices with new type abstractions (ThreadShell, ThreadTurnState). While runtime behavior should be equivalent, this restructures shared infrastructure that all components depend on and warrants human review to verify the migration is complete and correct.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant