package workspace import ( "fmt" "path/filepath" "strings" ) const DefaultBranch = "main" const ActiveStatus = "active" const ManagedRuntimeBackend = "host" const PendingProvisionState = "pending" type Project struct { ID string `json:"id"` Slug string `json:"slug"` Name string `json:"name"` RootPath string `json:"root_path"` DefaultBranch string `json:"default_branch"` Status string `json:"status"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } func (p Project) Validate() error { if p.Slug == "" { return fmt.Errorf("project slug is required") } if p.Name == "" { return fmt.Errorf("project name is required") } if p.RootPath == "" { return fmt.Errorf("project root path is required") } if p.DefaultBranch == "" { return fmt.Errorf("project default branch is required") } if p.Status == "" { return fmt.Errorf("project status is required") } return nil } func NormalizeProjectForCreate(value Project) Project { if strings.TrimSpace(value.DefaultBranch) == "" { value.DefaultBranch = DefaultBranch } if strings.TrimSpace(value.Status) == "" { value.Status = ActiveStatus } return value } type Workspace struct { ID string `json:"id"` ProjectID string `json:"project_id"` Slug string `json:"slug"` Name string `json:"name"` RootPath string `json:"root_path"` BaseBranch string `json:"base_branch"` WorktreeBranch string `json:"worktree_branch"` RuntimeBackend string `json:"runtime_backend"` Status string `json:"status"` ProvisionState string `json:"provision_state"` ProvisionError string `json:"provision_error"` LastProvisionedAt string `json:"last_provisioned_at,omitempty"` ContainerState string `json:"container_state,omitempty"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` } func (w Workspace) Validate() error { if w.ProjectID == "" { return fmt.Errorf("workspace project id is required") } if w.Slug == "" { return fmt.Errorf("workspace slug is required") } if w.Name == "" { return fmt.Errorf("workspace name is required") } if w.RootPath == "" { return fmt.Errorf("workspace root path is required") } if w.BaseBranch == "" { return fmt.Errorf("workspace base branch is required") } if w.WorktreeBranch == "" { return fmt.Errorf("workspace worktree branch is required") } if w.RuntimeBackend == "" { return fmt.Errorf("workspace runtime backend is required") } if w.Status == "" { return fmt.Errorf("workspace status is required") } if w.ProvisionState == "" { return fmt.Errorf("workspace provision state is required") } return nil } func NormalizeWorkspaceForCreate(value Workspace) Workspace { if strings.TrimSpace(value.BaseBranch) == "" { value.BaseBranch = DefaultBranch } if strings.TrimSpace(value.WorktreeBranch) == "" { value.WorktreeBranch = DefaultWorktreeBranch(value.Slug) } if strings.TrimSpace(value.RuntimeBackend) == "" { value.RuntimeBackend = ManagedRuntimeBackend } if strings.TrimSpace(value.Status) == "" { value.Status = ActiveStatus } if strings.TrimSpace(value.ProvisionState) == "" { value.ProvisionState = PendingProvisionState } return value } func ApplyManagedRuntimeConfig(value Workspace, workspacesDir, baseBranch string) Workspace { if dir := strings.TrimSpace(workspacesDir); dir != "" { value.RootPath = filepath.Join(dir, value.Slug) } value.BaseBranch = strings.TrimSpace(baseBranch) value.WorktreeBranch = DefaultWorktreeBranch(value.Slug) value.RuntimeBackend = ManagedRuntimeBackend value.Status = ActiveStatus return value } func DefaultWorktreeBranch(slug string) string { return "worktree/" + strings.TrimSpace(slug) }