feat(spaces): per-space base directories scope workspace roots to a Space - #179
Merged
Conversation
Foundation for per-Space base directories (scope a workspace root to a Space by folder prefix). No behavior change yet — just the primitive + storage. - Domain: path_is_within / longest_matching_base (segment-boundary aware, Windows + POSIX, longest-prefix wins) + the SpaceBaseDir entity. - Storage: migration 019 space_base_dirs (UNIQUE path = one owner per folder, FK cascade) + SpaceBaseDirRepository (list/add/remove + find_space_for_root longest-prefix lookup). - Tests: 4 domain prefix tests + 4 repo tests (CRUD, uniqueness, longest prefix, cascade). Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
An unmapped reported root that sits under a Space's base directory now falls back to THAT Space's Starter (scoped), not the global default Space. Exact WorkspaceBindings still win; roots outside every base dir still use the default Space. Because meta-tools resolve "which space" through the resolver, they auto-scope to the matched Space too. - FeatureSetResolverService gains a SpaceBaseDirRepository (wired through the GatewayDependencies, auto-derived from the database like the other repos). - Tier 1b: longest-prefix base-dir match → that Space's Starter. - Integration tests: under-base-dir scopes to that space, outside → default, nested → most-specific space wins, exact binding overrides base-dir scope. Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
- AppState gains the SpaceBaseDirRepository; Tauri commands list/add/remove_space_base_dir (add validates + normalizes the path and rejects a folder already owned by another space). - TS API: SpaceBaseDir + listSpaceBaseDirs/addSpaceBaseDir/removeSpaceBaseDir. - Spaces page: a folder-tree button per space opens a "Base directories" modal (multi-folder picker + list with remove). Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
… Space When a session's reported root is under a Space's base directory, the self-optimize meta-tools see ONLY that Space, and the mapping popup locks its Space field to it. - Resolver: new pub scoped_space_for_session(session_id). - meta-tools: mcpmux_list_spaces returns only the scoped Space; target_space_id resolves to it and rejects an explicit space_id that names a different Space. - WorkspaceNeedsBinding gains space_locked; handler sets it; the sheet disables the Space picker (user only picks the FeatureSet). - Tests: resolver scoped_space_for_session; TS sheet picker lock/unlock. Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Each Space can now claim one or more base directories. Any workspace root a connected client opens at or under a base dir is scoped to that Space — so the user doesn't have to map every folder, and a whole tree of projects belongs to the right Space automatically.
Concretely, when a session reports a root under Space X's base dir:
WorkspaceBindings still win; roots outside every base dir still use the default Space.mcpmux_list_spacesreturns only Space X, andtarget_space_idrejects an explicitspace_idnaming a different Space — no cross-Space reach.Design decisions (confirmed): longest-prefix wins, nesting allowed, one owner per exact path; the popup locks to the matched Space.
How it works
The resolver is the linchpin — meta-tools resolve "which space" through it and the popup gets the resolved
space_idin its event — so one resolver change makes most of the system respect base dirs, plus three targeted touch-ups.mcpmux-core):path_is_within/longest_matching_base(segment-boundary aware, Win+POSIX),SpaceBaseDirentity.space_base_dirs(UNIQUE path, FK cascade) +SpaceBaseDirRepository(find_space_for_rootlongest-prefix).scoped_space_for_session.list_spacesfilter +target_space_idlock.WorkspaceNeedsBinding.space_locked→ the sheet disables the Space picker.list/add/remove_space_base_dir(validate + normalize, reject cross-space dupes), TS API, and a Base directories modal on the Spaces page (multi-folder picker).Tests
scoped_space_for_session. Event payload stability. TS: sheet Space-picker lock/unlock.Built on top of #177 (merged).