refactor(settings): scope the settings project selector to settings
Picking a project in Settings called setActiveProject, which relocates the chat, the session list, the file tree and the Git surface. Reading another project's MCP servers or agents moved the user's whole app. It had to, because the configuration stores resolved the directory themselves from the active project and held one flat list. Each of them now takes an explicit directory — omitted still means the active project, so every caller outside Settings is unchanged — and keys loaded data by directory next to a flat mirror of the active project. Chat, autocompletes and pickers keep reading that mirror; a load for another directory writes only the map. A failed load restores that directory's previous list. Settings resolves its own directory through useSettingsDirectory, backed by a session-local settingsProjectPath that follows the active project until the user picks something else.
This commit is contained in:
@@ -198,6 +198,38 @@ These rules are important. Breaking them tends to reintroduce idle CPU churn, st
|
||||
9. Global session refresh must remain bounded and failure-isolated per directory.
|
||||
10. Global session cache must not drive live activity indicators or message-loading state.
|
||||
|
||||
### Configuration stores and the Settings directory
|
||||
|
||||
`useAgentsStore`, `useCommandsStore`, `useSkillsStore`, `useMcpConfigStore` and
|
||||
the provider half of `useConfigStore` describe **one project's configuration**.
|
||||
Two surfaces read them at once: the app (chat, autocompletes, pickers), which
|
||||
wants the active project, and Settings, whose own project selector may point
|
||||
somewhere else.
|
||||
|
||||
Each of them therefore keeps two things:
|
||||
|
||||
- a per-directory map (`agentsByDirectory`, `commandsByDirectory`,
|
||||
`skillsByDirectory`, `serversByDirectory`, `directoryScoped`);
|
||||
- a flat mirror (`agents`, `commands`, `skills`, `mcpServers`, `providers`) that
|
||||
tracks the **active** project only.
|
||||
|
||||
Every loader and mutation takes an explicit directory; omitting it means the
|
||||
active project, which is what non-Settings callers pass. A load for another
|
||||
directory writes the map and leaves the mirror alone, so browsing another
|
||||
project in Settings cannot change what chat sees. Components select through
|
||||
`selectAgentsForDirectory` / `selectCommandsForDirectory` /
|
||||
`selectSkillsForDirectory` / `selectMcpServersForDirectory` /
|
||||
`selectProvidersForDirectory`, which return stored arrays.
|
||||
|
||||
Settings resolves its directory through `useSettingsDirectory`, backed by
|
||||
`useUIStore.settingsProjectPath`. That selection is Settings-local and not
|
||||
persisted: it follows the active project until the user picks another one. The
|
||||
Settings project selector must never call `setActiveProject` — that relocates
|
||||
the chat, the session list and the file tree.
|
||||
|
||||
Failure is still not empty: a failed load restores that directory's previous
|
||||
list rather than clearing it.
|
||||
|
||||
## Selector Rules
|
||||
|
||||
Use leaf selectors.
|
||||
|
||||
Reference in New Issue
Block a user