fix: vault/workspace lifecycle — CreateVault creates workspace, SetCurrentVault loads workspace, ReloadPlugins keeps workspace capability, recursive tree rendering

This commit is contained in:
2026-06-17 14:26:49 +08:00
parent 5fa2c0ddf9
commit 67345a194a
7 changed files with 268 additions and 75 deletions
+7
View File
@@ -15,6 +15,7 @@ import (
"github.com/google/uuid"
"github.com/verstak/verstak-desktop/internal/core/events"
"github.com/verstak/verstak-desktop/internal/core/workspace"
)
// VaultStatus represents the current state of a vault.
@@ -114,6 +115,12 @@ func (v *Vault) CreateVault(path string) error {
return fmt.Errorf("failed to write vault.json: %w", err)
}
// Create workspace.json with root node
wsMgr := workspace.NewManager(vaultDir)
if err := wsMgr.Load(); err != nil {
return fmt.Errorf("failed to create workspace: %w", err)
}
v.mu.Lock()
v.status = StatusOpen
v.path = vaultDir
+110
View File
@@ -247,3 +247,113 @@ func TestVaultEvents_Published(t *testing.T) {
}
}
}
func TestCreateVault_CreatesWorkspace(t *testing.T) {
dir := t.TempDir()
vaultPath := filepath.Join(dir, "testvault")
bus := events.NewBus()
v := NewVault(bus)
if err := v.CreateVault(vaultPath); err != nil {
t.Fatalf("CreateVault: %v", err)
}
wsPath := filepath.Join(v.GetVaultPath(), ".verstak", "workspace.json")
data, err := os.ReadFile(wsPath)
if err != nil {
t.Fatalf("workspace.json not found: %v", err)
}
var ws struct {
SchemaVersion int `json:"schemaVersion"`
Nodes []struct {
ID string `json:"id"`
Type string `json:"type"`
Title string `json:"title"`
Status string `json:"status"`
ParentID string `json:"parentId"`
} `json:"nodes"`
CurrentNodeID string `json:"currentNodeId"`
}
if err := json.Unmarshal(data, &ws); err != nil {
t.Fatalf("failed to parse workspace.json: %v", err)
}
if ws.SchemaVersion != 1 {
t.Errorf("schemaVersion: got %d, want 1", ws.SchemaVersion)
}
if len(ws.Nodes) != 1 {
t.Fatalf("expected 1 root node, got %d", len(ws.Nodes))
}
if ws.Nodes[0].Type != "space" {
t.Errorf("root type: got %q, want %q", ws.Nodes[0].Type, "space")
}
if ws.Nodes[0].Title != "My Workspace" {
t.Errorf("root title: got %q, want %q", ws.Nodes[0].Title, "My Workspace")
}
if ws.Nodes[0].Status != "active" {
t.Errorf("root status: got %q, want %q", ws.Nodes[0].Status, "active")
}
if ws.CurrentNodeID != ws.Nodes[0].ID {
t.Errorf("currentNodeId should be root node id")
}
}
func TestOpenVault_WorkspaceLoads(t *testing.T) {
dir := t.TempDir()
vaultPath := filepath.Join(dir, "testvault")
bus := events.NewBus()
v := NewVault(bus)
if err := v.CreateVault(vaultPath); err != nil {
t.Fatalf("CreateVault: %v", err)
}
v.CloseVault()
if err := v.OpenVault(vaultPath); err != nil {
t.Fatalf("OpenVault: %v", err)
}
wsPath := filepath.Join(v.GetVaultPath(), ".verstak", "workspace.json")
data, err := os.ReadFile(wsPath)
if err != nil {
t.Fatalf("workspace.json not found after reopen: %v", err)
}
var ws struct {
Nodes []struct {
ID string `json:"id"`
Type string `json:"type"`
Title string `json:"title"`
} `json:"nodes"`
}
if err := json.Unmarshal(data, &ws); err != nil {
t.Fatalf("failed to parse workspace.json: %v", err)
}
if len(ws.Nodes) != 1 {
t.Fatalf("expected 1 node after reopen, got %d", len(ws.Nodes))
}
if ws.Nodes[0].Type != "space" {
t.Errorf("root type after reopen: got %q, want %q", ws.Nodes[0].Type, "space")
}
}
func TestCreateVault_VaultPathNormalized(t *testing.T) {
dir := t.TempDir()
vaultPath := filepath.Join(dir, "testvault")
bus := events.NewBus()
v := NewVault(bus)
if err := v.CreateVault(vaultPath); err != nil {
t.Fatalf("CreateVault: %v", err)
}
expectedPath := filepath.Join(vaultPath, "VerstakVault")
if v.GetVaultPath() != expectedPath {
t.Errorf("GetVaultPath: got %q, want %q", v.GetVaultPath(), expectedPath)
}
}