Workset Hierarchy Migration Tracker
Last updated: 2026-02-27
Goal
Transition from legacy template-centric workspace grouping to workset as the primary hierarchy concept, without a full frontend rewrite.
Current State (Verified)
- Dev mode uses isolated config at
~/.workset/dev/config.yamlviawails-ui/workset/dev_paths_dev.go. - App startup calls
ensureDevConfig()andGetConfig(), so config migrations onloadGlobal()run in dev. - Before this update, there was no migration that backfilled missing
workspaces[*].workset. - Result: existing entries without
worksetremained legacy-shaped and frontend fell back inconsistently.
Implemented in This Pass
- Config schema now persists as
worksets:(legacyworkspaces:still read for migration compatibility). internal/config/types.gointernal/config/defaults.gointernal/config/global.gointernal/config/global_update.go- Added
workset_catalogas explicit hierarchy data: - workset -> repos + feature threads.
- populated from existing workspace refs/workspace configs during migration.
- Added global-config migration for workspace workset backfill:
pkg/worksetapi/migrations.go- For each workspace with empty
workset:- use
templatewhen present; - otherwise derive from workspace repos (
repo-a,repo-a + repo-b, etc.); - fallback to workspace name if repo config is unavailable.
- use
- Persists changes through
ConfigUpdater(UpdateGlobal) when available. - Wired migration into config load path:
pkg/worksetapi/helpers.go(Service.loadGlobal).- Legacy
workspaces:key now triggers a write-back to canonicalworksets:on load. - This runs through the same
GetConfig()path Wails startup already calls. - Legacy
groupsis dropped during the legacy-key rewrite path so migrated config no longer shows template groups. - Ensured newly created workspaces always get
workset: pkg/worksetapi/helpers.go(registerWorkspace).- If
templateprovided,workset=template; elseworkset=workspace name. - Legacy
templateis now migration-only: - Migrated into
worksetand stripped on save/update. - Workspace snapshot identity now prefers explicit
worksetover repo heuristics: pkg/worksetapi/workspace_snapshots.goworkset_keynow derives from normalizedworksetwhen present (workset:<slug>).- Fixes incorrect top-bar workset options when multiple threads belong to one workset.
- Terminal cockpit duplicate selector reduction:
wails-ui/workset/frontend/src/App.svelte- top context-bar workset switcher is hidden in
terminal-cockpit(thread navigation remains in the left panel). - Workset hub reactivity hardening:
wails-ui/workset/frontend/src/lib/components/views/WorksetHubView.svelte- prop-sync for
groupMode/layoutModenow only applies when controlled props are explicitly provided. - avoids uncontrolled-mode resets and reduces risk of effect depth loops.
- Settings terminology surface update:
wails-ui/workset/frontend/src/lib/components/settings/SettingsSidebar.sveltewails-ui/workset/frontend/src/lib/components/SettingsPanel.svelte- Removed Templates (
groups) from visible Settings navigation and section routing. - Create workset flow update (repo-catalog-first):
wails-ui/workset/frontend/src/lib/components/workspace-action/WorkspaceActionCreateForm.sveltewails-ui/workset/frontend/src/lib/components/workspace-action/WorkspaceActionFormContent.sveltewails-ui/workset/frontend/src/lib/components/WorkspaceActionModal.sveltewails-ui/workset/frontend/src/App.svelte- New workset path now opens modal create flow with searchable repo-catalog multi-select instead of onboarding entry from rail.
- Create workset flow refinement (template-free + add-repo inline):
wails-ui/workset/frontend/src/lib/services/workspaceActionContextService.tswails-ui/workset/frontend/src/lib/services/workspaceActionService.tswails-ui/workset/frontend/src/lib/components/workspace-action/WorkspaceActionCreateForm.svelte- Create flow no longer loads template groups; it supports:
- repo-catalog selection
- inline add of direct repository sources
- optional “save to catalog” per direct source.
- New thread entrypoint under workset Threads:
wails-ui/workset/frontend/src/lib/components/chrome/ExplorerPanel.sveltewails-ui/workset/frontend/src/lib/components/views/SpacesWorkbenchView.sveltewails-ui/workset/frontend/src/App.svelte- Added per-workset “+” action in Threads sections that opens a thread-scoped create modal (
create-thread) with:- thread name input
- seeded repo selection from the selected workset’s repos.
- Cockpit hierarchy alignment with global explorer + global changes drawer:
wails-ui/workset/frontend/src/lib/components/views/SpacesWorkbenchView.svelte- In main-window (
useGlobalExplorer=true) mode:- suppresses the legacy cockpit header strip (thread/branch meta) so context is owned by the top context bar.
- suppresses the legacy inline diff-summary sidebar so diff context is owned by the global right-side changes drawer.
- Popout mode keeps the local header/diff affordances (no global explorer/chrome there).
Migration Lifecycle Contract
To make migration removal deliberate (instead of ad hoc), global config migrations now run through an explicit ordered plan in pkg/worksetapi/migrations.go:
2026-02-workspaces-to-worksets2026-02-group-remotes-to-aliases
Each migration now carries:
- a stable ID
- a summary of what it normalizes
- a remove_after guidance string documenting the deletion trigger
Removal trigger
Delete a migration only when all are true:
- Configs loaded in the supported upgrade window no longer contain the legacy key/shape.
- Migration tests remain green with the migration code removed or no-op’d.
- Two full minor releases have shipped with no regressions attributable to that legacy shape.
Test coverage
pkg/worksetapi/migrations_workset_test.go now asserts:
- migration plan order is stable
- each migration includes removal metadata
- legacy key rewrite is idempotent across repeated loads
Tests Added/Updated
- Added:
pkg/worksetapi/migrations_workset_test.go- migrates missing
worksetfrom workspace repo config. - migrates missing
worksetfrom legacytemplate.
- migrates missing
pkg/worksetapi/workspace_snapshots_test.goTestListWorkspaceSnapshotsUsesExplicitWorksetIdentityvalidates explicit workset key/label behavior.
- Updated:
pkg/worksetapi/service_workspaces_test.go- asserts create flow writes
worksetby default. - asserts template input also sets
workset.
- asserts create flow writes
Next Phases
- Frontend terminology cleanup
- Remove primary-nav dependence on
templatelabels. - Keep backend compatibility fields for two minor releases.
- Workspace switch UX
- Keep one selector in top context bar once a workset is selected.
- Avoid duplicate selector in left rail.
- Thread/feature hierarchy
- Define where feature threads are sourced and stored (workspace state vs global config).
- Final deprecation
- Remove
templatewrite paths and keep read-only compatibility migration.