Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .design/cleanup-candidates.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ The runtime broker's agent creation path builds an `api.StartOptions` struct and
| `finalizeEnv` | `handlers.go:1932-2086` | Env-gather completion: env merge → hydrate template → git-clone → start |

Each handler independently:
1. Resolves the hub-native grove path from `GroveSlug` (identical `~/.scion/groves/<slug>` block, duplicated at lines 323-350 and 1032-1054)
1. Resolves the hub-managed grove path from `GroveSlug` (identical `~/.scion/groves/<slug>` block, duplicated at lines 323-350 and 1032-1054)
2. Builds the merged env map with hub endpoint, broker name, debug flag, auth tokens
3. Translates `SCION_TELEMETRY_ENABLED` into `TelemetryOverride`
4. Hydrates templates from Hub
Expand Down Expand Up @@ -108,7 +108,7 @@ func (s *Server) buildStartContext(ctx context.Context, r *http.Request, req Cre
```

This function encapsulates:
- Hub-native grove path resolution
- Hub-managed grove path resolution
- Env merging (resolved env + config env + auth tokens + hub endpoint + broker identity + debug)
- Template hydration
- Git-clone env injection
Expand Down
2 changes: 1 addition & 1 deletion .design/dispatch-cleanup.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ These four changes will materially improve robustness, reliability, and future d
- values must be redacted in broker debug logs

### Why Local Settings Are Sometimes Ignored
In Hub-connected container flows, local grove settings may not represent the active Hub endpoint (for example, combo/hub-native routing or remote broker dispatch). In that mode, dispatch/broker authoritative inputs intentionally take precedence over stale local settings.
In Hub-connected container flows, local grove settings may not represent the active Hub endpoint (for example, combo/hub-managed routing or remote broker dispatch). In that mode, dispatch/broker authoritative inputs intentionally take precedence over stale local settings.

## Troubleshooting Matrix

Expand Down
10 changes: 5 additions & 5 deletions .design/git-grove-duplicates.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Each grove has its own set of agents, templates, and settings. Agents in one gro

- Merging or synchronizing work between groves sharing the same repository.
- Cross-grove agent visibility or communication.
- Changing the hub-native (non-git) grove model.
- Changing the hub-managed (non-git) grove model.

---

Expand Down Expand Up @@ -87,7 +87,7 @@ Since SQLite doesn't support `ALTER TABLE ... DROP CONSTRAINT`, the migration wi

**New behavior:** Grove IDs are always randomly generated UUIDs (`uuid.New()`), regardless of whether the grove has a git remote.

**Rationale:** Deterministic IDs were designed to enforce the 1:1 mapping. With multiple groves per URL, deterministic IDs would cause collisions. Random UUIDs are already used for hub-native groves and work correctly.
**Rationale:** Deterministic IDs were designed to enforce the 1:1 mapping. With multiple groves per URL, deterministic IDs would cause collisions. Random UUIDs are already used for hub-managed groves and work correctly.

**`HashGroveID()` is retained** but repurposed: it is no longer used for grove ID generation. It may still be useful for other deterministic identifiers (e.g., cache keys), so it is not removed. Callers that used it for grove ID generation are updated.

Expand All @@ -96,7 +96,7 @@ Since SQLite doesn't support `ALTER TABLE ... DROP CONSTRAINT`, the migration wi
### 3.3 Enforce Unique Slugs with Serial Numbering

Slugs must remain unique because they are used in:
- Filesystem paths (`~/.scion/groves/<slug>/` for hub-native, `~/.scion/grove-configs/<slug>__<uuid>/` for external)
- Filesystem paths (`~/.scion/groves/<slug>/` for hub-managed, `~/.scion/grove-configs/<slug>__<uuid>/` for external)
- API routing (`/api/v1/groves/<slug-or-id>/...`)
- CLI references (`scion start agent --grove <slug>`)

Expand Down Expand Up @@ -167,7 +167,7 @@ All three workspace strategies (represented as three modes at the model layer) c

- **Per-agent clone** (`GitClone` set, `SharedWorkspace=false`): Each agent in a git grove clones the repository independently inside its container. This is the default for git groves.
- **Shared workspace clone** (`GitClone` unset, `SharedWorkspace=true`, `Workspace` set): A single shared git clone is mounted by all agents in the grove, rather than each agent cloning independently.
- **Hub-native workspace** (`GitClone` unset, `SharedWorkspace=false`, `Workspace` set): Non-git groves with a hub-managed filesystem.
- **Hub-managed workspace** (`GitClone` unset, `SharedWorkspace=false`, `Workspace` set): Non-git groves with a hub-managed filesystem.

The workspace strategy is determined by grove configuration (specifically the `scion.dev/workspace-mode` label), not by the number of groves sharing a URL. Multiple groves sharing the same git remote may each independently choose their own workspace strategy.

Expand Down Expand Up @@ -272,7 +272,7 @@ GetInstallationForRepository(ctx context.Context, repoFullName string) (*GitHubI
**Cons:**
- The sequence number itself needs coordination (what if two clients try to create grove #2 simultaneously?).
- Deterministic creation was valuable precisely because it avoided coordination — adding a sequence number undermines the benefit.
- Random UUIDs are simpler and already proven (hub-native groves use them).
- Random UUIDs are simpler and already proven (hub-managed groves use them).

**Decision:** Rejected. Random UUIDs are simpler and sufficient.

Expand Down
50 changes: 25 additions & 25 deletions .design/git-workspace-hybrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Today, Hub-created groves come in two flavors:
| Type | Workspace Strategy | Agent Isolation |
|------|-------------------|-----------------|
| **Git-based** (`gitRemote` set) | Each agent clones the repo independently into its container. Workspace is ephemeral — lost on container deletion. | Full isolation: each agent has its own `.git`, branch, and working tree. |
| **Hub-native** (no `gitRemote`) | A single shared workspace at `~/.scion/groves/<slug>/` is mounted into all agents. | No isolation: agents share the same files. Concurrent writes can conflict. |
| **Hub-managed** (no `gitRemote`) | A single shared workspace at `~/.scion/groves/<slug>/` is mounted into all agents. | No isolation: agents share the same files. Concurrent writes can conflict. |

Both models have significant limitations for a common use case: **teams that want a git-backed project but prefer a shared, persistent workspace** on the Hub rather than ephemeral per-agent clones.

Expand All @@ -26,15 +26,15 @@ Both models have significant limitations for a common use case: **teams that wan
3. **No shared state** — agents cannot see each other's file changes unless they push to the remote and pull.
4. **Clone latency** — each agent start incurs clone time, especially for large repos.

**Pain points with the current hub-native model:**
**Pain points with the current hub-managed model:**

1. **No git integration** — no ability to commit, push, create branches, or open PRs.
2. **No source of truth** — the workspace is a bare directory with no version history.
3. **No reproducibility** — if the workspace is lost, there's no way to restore it from a remote.

### 1.2 Proposal

Introduce a **git-workspace hybrid** grove mode: a git grove that provisions a **single shared git clone** into the hub-native workspace path instead of per-agent clones. Agents mount this shared workspace, just as hub-native groves work today.
Introduce a **git-workspace hybrid** grove mode: a git grove that provisions a **single shared git clone** into the hub-managed workspace path instead of per-agent clones. Agents mount this shared workspace, just as hub-managed groves work today.

This is offered as a **sub-mode of git-based groves** — the existing per-agent clone behavior is retained as the default. Users choose the workspace mode when creating a git grove.

Expand All @@ -49,7 +49,7 @@ This combines the benefits of both models:
1. Allow creating a git grove that provisions a shared, persistent workspace.
2. The workspace is a real git clone — agents can commit, branch, push, and pull.
3. Only one clone operation per grove (not per agent).
4. Agents share the workspace filesystem, similar to hub-native groves.
4. Agents share the workspace filesystem, similar to hub-managed groves.
5. Support private repositories via `GITHUB_TOKEN` or GitHub App credentials.

### 1.4 Non-Goals
Expand Down Expand Up @@ -85,13 +85,13 @@ This combines the benefits of both models:
- Agents still can't see each other's uncommitted changes (separate working trees).
- Worktree creation adds startup latency (though less than a full clone).
- More complex lifecycle management (worktree cleanup, branch tracking).
- Doesn't match the hub-native "shared workspace" mental model that users expect.
- Doesn't match the hub-managed "shared workspace" mental model that users expect.

**Verdict:** This is a valid future extension that would leverage the existing local-mode worktree patterns, but it doesn't fulfill the "shared workspace" goal for this scope. It's essentially an optimization of the current git-based model. Marked as a potential future option that could be offered alongside the shared workspace mode.

### 2.2 Alternative B: Clone Once, Mount Shared (Proposed)

**Concept:** Clone the repo once into the hub-native workspace path. All agents mount the same directory. The workspace is a normal git working tree (not bare).
**Concept:** Clone the repo once into the hub-managed workspace path. All agents mount the same directory. The workspace is a normal git working tree (not bare).

```
~/.scion/groves/<slug>/
Expand All @@ -106,14 +106,14 @@ This combines the benefits of both models:
- Agents can see each other's file changes in real-time.
- Full git operations available (commit, push, pull, branch).
- Minimal lifecycle complexity — it's just a directory.
- Matches hub-native behavior exactly (just with git pre-initialized).
- Matches hub-managed behavior exactly (just with git pre-initialized).

**Cons:**
- No isolation: concurrent agent writes can conflict.
- Single branch at a time (or agents must coordinate git operations).
- Potential for `.git` lock contention with concurrent git operations.

**Verdict:** This is the simplest approach and matches the user's stated desire for a "shared workspace with git". The lack of isolation is a known trade-off that users accept when choosing hub-native groves today.
**Verdict:** This is the simplest approach and matches the user's stated desire for a "shared workspace with git". The lack of isolation is a known trade-off that users accept when choosing hub-managed groves today.

### 2.3 Alternative C: Git Clone + GCS Sync Hybrid

Expand Down Expand Up @@ -150,7 +150,7 @@ This combines the benefits of both models:
**Alternative B (Clone Once, Mount Shared)** is the proposed approach, offered as a sub-mode of git groves alongside the existing per-agent clone mode (Alternative D). It provides the best balance of simplicity, git integration, and shared workspace behavior. The isolation trade-offs are acceptable because:

1. Users choosing "shared workspace" mode are explicitly opting into shared state.
2. The same trade-off already exists for hub-native groves.
2. The same trade-off already exists for hub-managed groves.
3. Per-agent isolation can be layered on later (Alternative A) as a separate grove option.

---
Expand Down Expand Up @@ -245,12 +245,12 @@ This is simpler than maintaining a grove status state machine for provisioning

### 3.3 Agent Workspace Mounting

Once the shared workspace is cloned, agents mount it identically to hub-native groves:
Once the shared workspace is cloned, agents mount it identically to hub-managed groves:

```go
// In agent provisioning (pkg/agent/provision.go):
if grove.IsSharedWorkspace() {
// Mount the shared workspace — same as hub-native
// Mount the shared workspace — same as hub-managed
workspaceSource = hubNativeGrovePath(grove.Slug)
// Skip worktree creation — workspace already exists
shouldCreateWorktree = false
Expand Down Expand Up @@ -306,7 +306,7 @@ The existing `POST /api/v1/groves` handler needs to:

1. Accept a new `workspaceMode` field (or detect it from labels).
2. When `workspaceMode: "shared"` and `gitRemote` is set:
a. Create the hub-native workspace directory (`~/.scion/groves/<slug>/`).
a. Create the hub-managed workspace directory (`~/.scion/groves/<slug>/`).
b. Perform the host-side git clone into the workspace directory.
c. On clone success: create the grove record.
d. On clone failure: clean up the workspace directory and return an error.
Expand Down Expand Up @@ -337,7 +337,7 @@ When an agent is started on a shared-workspace git grove:

1. **Skip git clone** — the workspace already contains a clone.
2. **Skip worktree creation** — agents share the workspace directly.
3. **Mount shared workspace** — same bind mount as hub-native groves.
3. **Mount shared workspace** — same bind mount as hub-managed groves.
4. **Configure credential helper** — per-agent `$HOME/.gitconfig` with `GITHUB_TOKEN`.
5. **Branch field behavior** — the agent creation form preserves the branch name field. For shared-workspace groves, the default value is the workspace's current branch (instead of an agent-named branch as used for clone-based agents). Agents can change branches but must coordinate since only one branch can be checked out at a time.

Expand All @@ -358,7 +358,7 @@ case isGit && noExplicitWorkspace:
// (existing behavior)

default:
// Hub-native: mount shared workspace
// Hub-managed: mount shared workspace
// (existing behavior)
}
```
Expand All @@ -369,7 +369,7 @@ The existing `handleGroveWorkspace` handler (`grove_workspace_handlers.go:84-86`

```go
if grove.GitRemote != "" {
Conflict(w, "Workspace file management is only available for hub-native groves")
Conflict(w, "Workspace file management is only available for hub-managed groves")
return
}
```
Expand All @@ -378,7 +378,7 @@ For shared-workspace groves, this check should be relaxed:

```go
if grove.GitRemote != "" && !grove.IsSharedWorkspace() {
Conflict(w, "Workspace file management is only available for hub-native and git-shared groves")
Conflict(w, "Workspace file management is only available for hub-managed and git-shared groves")
return
}
```
Expand All @@ -396,7 +396,7 @@ With a shared workspace, two agents running concurrently could:
- Run `git checkout` to different branches
- Run conflicting git operations (e.g., concurrent commits)

**Resolution:** No formal coordination mechanism. This is up to the grove owner and users to manage — the same as hub-native groves today. Document the shared workspace semantics clearly and let users decide coordination strategies via agent instructions.
**Resolution:** No formal coordination mechanism. This is up to the grove owner and users to manage — the same as hub-managed groves today. Document the shared workspace semantics clearly and let users decide coordination strategies via agent instructions.

### 4.2 Branch Management

Expand Down Expand Up @@ -442,7 +442,7 @@ No credential files are stored in the workspace (see Section 3.4), so there is n

The grove creation flow uses a two-step type selection:

1. **Primary type choice:** `Hub Workspace` or `Git Repository`
1. **Primary type choice:** `Hub-managed Workspace` or `Git Repository`
2. **Git mode choice (shown when Git Repository is selected):**
- `Per-agent clone` (default) — each agent gets its own clone (existing behavior).
- `Shared workspace` — a single shared clone mounted by all agents (new).
Expand All @@ -457,7 +457,7 @@ type GitWorkspaceMode = 'per-agent' | 'shared';

```html
<!-- Primary type selector -->
<sl-option value="hub">Hub Workspace</sl-option>
<sl-option value="hub">Hub-managed Workspace</sl-option>
<sl-option value="git">Git Repository</sl-option>

<!-- Sub-mode selector (visible when git is selected) -->
Expand All @@ -477,7 +477,7 @@ When `shared` is selected:
For shared-workspace git groves, the grove detail page should show:
- Git remote URL (linked to GitHub).
- Current branch checked out.
- File browser (reuse hub-native workspace file listing).
- File browser (reuse hub-managed workspace file listing).
- A "Pull Latest" action button.

### 5.3 Agent Creation Form
Expand Down Expand Up @@ -517,15 +517,15 @@ The branch name field on the new-agent form adapts its default based on workspac
- ✅ Hub dispatcher resolves `grove.IsSharedWorkspace()` and propagates to broker.
- ✅ Broker injects `SCION_SHARED_WORKSPACE` env var for sciontool.
2. ✅ Mount shared workspace path for agents on shared-workspace groves.
- ✅ Hub sets workspace to hub-native grove path; broker passes through.
- ✅ Hub sets workspace to hub-managed grove path; broker passes through.
- ✅ ProvisionAgent takes explicit workspace path (skips worktree creation).
3. ✅ Configure per-agent credential helper in `$HOME/.gitconfig` with `GITHUB_TOKEN`.
- ✅ ProvisionAgent writes credential helper to agent home `.gitconfig`.
- ✅ sciontool `configureSharedWorkspaceGit()` handles in-container setup with GitHub App support.
4. ✅ Update default branch name logic for new-agent form.
- ✅ Shared-workspace agents default to grove's `scion.dev/default-branch` label (or "main").
5. ✅ Test concurrent agent access to shared workspace.
- ✅ Documented as user responsibility (same as hub-native groves).
- ✅ Documented as user responsibility (same as hub-managed groves).

### Phase 4: Web UI ✅ Completed

Expand All @@ -535,7 +535,7 @@ The branch name field on the new-agent form adapts its default based on workspac
- ✅ `workspaceMode` and `scion.dev/workspace-mode` label sent in API request.
2. ✅ Enable workspace file browser for shared-workspace groves.
- ✅ `shouldShowFilesSection()` and `getFileTabs()` updated to include workspace tab for shared-workspace groves.
- ✅ File loading on page load triggers for shared-workspace groves (same as hub-native).
- ✅ File loading on page load triggers for shared-workspace groves (same as hub-managed).
3. ✅ Add "Pull Latest" action to grove detail page.
- ✅ Backend `POST /api/v1/groves/{id}/workspace/pull` endpoint with `git pull --ff-only`.
- ✅ `PullSharedWorkspace` utility function in `pkg/util/git.go` with token auth and credential sanitization.
Expand Down Expand Up @@ -580,7 +580,7 @@ The branch name field on the new-agent form adapts its default based on workspac

| # | Question | Status | Decision |
|---|----------|--------|----------|
| 1 | **Workspace model?** | Resolved | Shared workspace (Alternative B). Simplest model, matches hub-native mental model. |
| 1 | **Workspace model?** | Resolved | Shared workspace (Alternative B). Simplest model, matches hub-managed mental model. |
| 2 | **Retain per-agent clone?** | Resolved | Yes. Per-agent clone remains the default. Shared workspace is a sub-mode choice. |
| 3 | **Type modeling?** | Resolved | Sub-type of git grove via `scion.dev/workspace-mode` label. GroveType remains `"git"`. See Section 3.1 for rationale. |
| 4 | **Clone mechanism?** | Resolved | Host-side clone by Hub/broker. Simpler, faster, better error handling than bootstrap container. |
Expand Down Expand Up @@ -612,7 +612,7 @@ The branch name field on the new-agent form adapts its default based on workspac

| File | Relevance |
|------|-----------|
| `pkg/hub/handlers.go` | Grove creation handler. Hub-native workspace init. |
| `pkg/hub/handlers.go` | Grove creation handler. Hub-managed workspace init. |
| `pkg/hub/grove_workspace_handlers.go` | Workspace file management (currently rejects git groves). |
| `pkg/agent/provision.go` | Agent provisioning. Workspace resolution and worktree creation. |
| `pkg/runtime/common.go` | Container workspace mounting logic. |
Expand Down
2 changes: 1 addition & 1 deletion .design/grove-dirs.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ This location is:
- Per-grove (naturally scoped)
- Persistent across agent restarts and reprovisioning

For hub-native groves, shared dirs live at `~/.scion/grove-configs/<hub-grove>/shared-dirs/<name>/` on each broker — the same grove-configs path used for agent homes. The `~/.scion/groves/<hub-grove>/` path is reserved for hub-native workspaces, not configuration state.
For hub-managed groves, shared dirs live at `~/.scion/grove-configs/<hub-grove>/shared-dirs/<name>/` on each broker — the same grove-configs path used for agent homes. The `~/.scion/groves/<hub-grove>/` path is reserved for hub-managed workspaces, not configuration state.

## Mount Target Strategy

Expand Down
Loading
Loading