Files
headquarter/openspec/explorations/config-profile-multi-repo-mounts.md
T
Alex Blank 0e6521e433 feat: config profile multi-repo mounts
- Add mappings array support to git_mount entries
- Clone repository once per git_mount entry, mount multiple subdirectories
- Normalize legacy source_path+target_path to mappings on read
- Update _merge_git_mounts to dedup by (remote_url, branch) and concatenate mappings
- Add _normalize_git_mount, _clone_git_repo, _resolve_git_mount_mappings helpers
- Update GitMountItem Pydantic model with GitMountMapping and model_validator
- Update frontend GitMountEditor component with mappings UI
- Auto-convert legacy git mount entries to mappings format on load
- Add 15 backend unit tests for normalization, resolution, and glob expansion
- Update existing config profile resolver tests for new merge behavior

Quality gates: pytest 167 passed, frontend typecheck clean

Addresses: config-profile-multi-repo-mounts
2026-05-28 23:35:22 +02:00

121 lines
3.8 KiB
Markdown

# Exploration: Config Profile Multi-Repo Mounts
## Problem
Config Profiles support `git_mounts` — cloning repositories and mounting them into containers. However, each `git_mount` entry clones **one** source path from **one** repo. If a user wants to mount multiple directories from the same repository (e.g., a monorepo), they must add multiple `git_mount` entries, which results in **cloning the same repository multiple times**.
### Current git_mount schema (one mapping per entry)
```json
{
"remote_url": "https://github.com/user/monorepo.git",
"source_path": "packages/backend",
"target_path": "/app/backend",
"branch": "main"
}
```
To mount 3 directories from the same monorepo, the profile needs 3 entries, each triggering a separate clone of the full repository.
## Pain Points
1. **Redundant clones**: Cloning the same repo N times wastes time and disk space.
2. **Slow instance startup**: Each clone adds 5-30 seconds depending on repo size.
3. **Inconsistent branch state**: Each entry independently checks out the branch — they could drift if the branch moves between clones.
4. **Poor monorepo support**: Monorepos are common; users expect to mount multiple packages.
## Scenarios
### Scenario A: Monorepo with multiple packages
User has a monorepo `corp/monorepo` with:
- `packages/api` → needs to be at `/app/api`
- `packages/web` → needs to be at `/app/web`
- `packages/shared` → needs to be at `/app/shared`
They want to mount all three into a single tool instance.
### Scenario B: Docs + Code sidecar
User wants to mount both:
- `src/``/workspace/src`
- `docs/``/workspace/docs`
from the same repo.
### Scenario C: Backward compatibility
Existing profiles with single `source_path`/`target_path` should continue working without migration.
## Design Directions
### Direction A: `mappings` array on git_mount entry
Add a `mappings` array to each git_mount entry. The repo is cloned once, and each mapping creates a separate bind mount.
```json
{
"remote_url": "https://github.com/user/monorepo.git",
"branch": "main",
"mappings": [
{"source_path": "packages/api", "target_path": "/app/api"},
{"source_path": "packages/web", "target_path": "/app/web"}
]
}
```
**Pros**:
- Clean, explicit grouping
- Single clone per `remote_url + branch` combo
- Easy to understand
- Backward-compatible: legacy `source_path` + `target_path` can be treated as a single-entry `mappings` array
**Cons**:
- Slightly more verbose JSON
- Frontend form needs a nested list UI
### Direction B: Auto-dedup by remote_url + branch
Keep the flat list format, but internally group entries by `remote_url + branch` and clone once.
```json
[
{"remote_url": "...", "source_path": "a", "target_path": "/a", "branch": "main"},
{"remote_url": "...", "source_path": "b", "target_path": "/b", "branch": "main"}
]
```
**Pros**:
- No schema change
- Transparent to users
**Cons**:
- Magic behavior (not obvious why clones are shared)
- Harder to reason about branch conflicts (what if same repo, different branches?)
- Frontend doesn't show the grouping
### Direction C: Repo references + mount definitions split
Split into two concepts:
1. `git_repos` — list of repos to clone (with branch)
2. `git_mounts` — reference a repo by name and specify source/target
**Pros**:
- Very explicit
- Supports advanced scenarios (SSH keys per repo)
**Cons**:
- Breaking schema change
- Overkill for the current use case
- Heavy migration burden
## Recommendation
**Direction A (mappings array)** with backward-compatibility shim:
- Add optional `mappings` field to git_mount entries
- If `mappings` is absent, treat `source_path` + `target_path` as a single mapping
- Clone once per `remote_url + branch`, apply all mappings from the same entry
- No migration needed for existing data
This balances clarity, functionality, and backward compatibility.