Why
#58 ("Git-native workspace") sits as a roadmap goal — a workspace's state (URLs, envs, collections, recordings, scripts, AI config overrides) should be checkable into a git repo so a team can git push / git pull their context.
After #116 (workspaces with per-user-folder scoping) + #144 (chunked recording storage with per-workspace roots) + #144 Phase 1.7 (per-workspace recording-storage mode), the architecture is almost there but on a different axis. We have:
A git-backed workspace adds a second axis: storage location. The two compose orthogonally.
Proposal — workspace.storageRoot
A workspace gains an optional storageRoot field:
Resolution
- When
storageRoot is unset (today's default): recordings live at ~/.bowire/workspaces/<wsId>/recordings/. No change.
- When
storageRoot is set: recordings live at <storageRoot>/recordings/. Everything else (envs, collections, scripts) routes the same way.
- Frontend sends
storageRoot=... as a query param on every workspace-scoped API call (next to the existing workspaceId=...).
- Backend's
BowireUserContext.GetUserPath() gets an overload that accepts an explicit root; the resolution chain is storageRoot → multi-tenant per-identity → single-user default.
Operator surface
In the Workspaces rail-mode detail pane, add a Storage location section under the existing Recording storage section:
| Field |
Behaviour |
[unset] |
Default — user folder |
<path> |
Custom — workspace state lives there |
[+ Init git workspace…] |
Opens a dialog: pick a directory, run git init, set storageRoot to that path, drop a .gitignore excluding recordings/bodies/ (content-addressed blobs are large; let teams choose) |
A "Sync to git" action (manual commit + push) can land later; for v1 the operator runs git commands themselves.
Composes with
Acceptance
Out of scope
- Auto-commit / auto-push on every change. Too noisy; the operator owns git operations.
- Conflict resolution UI for
git pull showing merge conflicts in the workbench. Operator handles in their git tooling.
- Multi-root workspaces (one workspace pulling state from multiple git repos). Niche; defer until a real ask.
- Cloud-hosted shared workspaces (S3, blob). Different storage class entirely; separate issue.
Why
#58 ("Git-native workspace") sits as a roadmap goal — a workspace's state (URLs, envs, collections, recordings, scripts, AI config overrides) should be checkable into a git repo so a team can
git push/git pulltheir context.After #116 (workspaces with per-user-folder scoping) + #144 (chunked recording storage with per-workspace roots) + #144 Phase 1.7 (per-workspace recording-storage mode), the architecture is almost there but on a different axis. We have:
~/.bowire/workspaces/<wsId>/viaBowireUserContext.both/browser-only/disk-only— controls caching strategy, not WHERE the data lands.A git-backed workspace adds a second axis: storage location. The two compose orthogonally.
Proposal —
workspace.storageRootA workspace gains an optional
storageRootfield:{ "id": "ws_payments", "name": "Payments — staging", "color": "#22c55e", "storageRoot": "/Users/me/work/payments/.bowire", // ← NEW "recordingStorageMode": "both" }Resolution
storageRootis unset (today's default): recordings live at~/.bowire/workspaces/<wsId>/recordings/. No change.storageRootis set: recordings live at<storageRoot>/recordings/. Everything else (envs, collections, scripts) routes the same way.storageRoot=...as a query param on every workspace-scoped API call (next to the existingworkspaceId=...).BowireUserContext.GetUserPath()gets an overload that accepts an explicit root; the resolution chain isstorageRoot → multi-tenant per-identity → single-user default.Operator surface
In the Workspaces rail-mode detail pane, add a Storage location section under the existing Recording storage section:
[unset]<path>[+ Init git workspace…]git init, set storageRoot to that path, drop a.gitignoreexcludingrecordings/bodies/(content-addressed blobs are large; let teams choose)A "Sync to git" action (manual commit + push) can land later; for v1 the operator runs git commands themselves.
Composes with
both/browser-only/disk-only. Typical: git-backed +disk-onlyfor big captures the team shares.storageRoot"export" becomes "git push".Acceptance
workspace.storageRootfield persisted with the workspace.storageRoot=...on every recording / env / collection API call when set...traversal or absolute paths outside the OS allow-list (configurable per host).[+ Init git workspace…]runsgit init, drops a default.gitignore, sets storageRoot.Out of scope
git pullshowing merge conflicts in the workbench. Operator handles in their git tooling.