Refactor, add consts

Change-Id: Iabb1738e90d06ec9830a3d9efcf35cfecc2d86ce
diff --git a/server/tm/git_tm/git_task_manager.go b/server/tm/git_tm/git_task_manager.go
index 5c43828..edfb476 100644
--- a/server/tm/git_tm/git_task_manager.go
+++ b/server/tm/git_tm/git_task_manager.go
@@ -16,21 +16,50 @@
 	"gopkg.in/yaml.v3"
 )
 
+const (
+	// File system constants
+	DefaultFileMode = 0755
+	TaskFileMode    = 0644
+	TaskFileExt     = ".md"
+	
+	// Frontmatter constants
+	FrontmatterSeparator = "---\n"
+	
+	// Task ID format
+	TaskIDPrefix = "task-"
+)
+
+// UserService defines interface for user-related operations
+type UserService interface {
+	GetUserName(userID string) (string, error)
+}
+
+// DefaultUserService provides a simple implementation that uses userID as name
+type DefaultUserService struct{}
+
+func (dus *DefaultUserService) GetUserName(userID string) (string, error) {
+	// For now, just return the userID as the name
+	// This can be enhanced to lookup from a proper user service
+	return userID, nil
+}
+
 // GitTaskManager implements TaskManager interface using git as the source of truth
 type GitTaskManager struct {
-	git      git.GitInterface
-	repoPath string
-	tasksDir string
-	logger   *slog.Logger
+	git         git.GitInterface
+	repoPath    string
+	tasksDir    string
+	logger      *slog.Logger
+	userService UserService
 }
 
 // NewGitTaskManager creates a new GitTaskManager instance
 func NewGitTaskManager(git git.GitInterface, repoPath string, logger *slog.Logger) *GitTaskManager {
 	return &GitTaskManager{
-		git:      git,
-		repoPath: repoPath,
-		tasksDir: repoPath,
-		logger:   logger,
+		git:         git,
+		repoPath:    repoPath,
+		tasksDir:    filepath.Join(repoPath, "tasks"),
+		logger:      logger,
+		userService: &DefaultUserService{},
 	}
 }
 
@@ -40,16 +69,34 @@
 		logger = slog.Default()
 	}
 	return &GitTaskManager{
-		git:      git,
-		repoPath: repoPath,
-		tasksDir: repoPath,
-		logger:   logger,
+		git:         git,
+		repoPath:    repoPath,
+		tasksDir:    filepath.Join(repoPath, "tasks"),
+		logger:      logger,
+		userService: &DefaultUserService{},
+	}
+}
+
+// NewGitTaskManagerWithUserService creates a new GitTaskManager with custom user service
+func NewGitTaskManagerWithUserService(git git.GitInterface, repoPath string, logger *slog.Logger, userService UserService) *GitTaskManager {
+	if logger == nil {
+		logger = slog.Default()
+	}
+	if userService == nil {
+		userService = &DefaultUserService{}
+	}
+	return &GitTaskManager{
+		git:         git,
+		repoPath:    repoPath,
+		tasksDir:    filepath.Join(repoPath, "tasks"),
+		logger:      logger,
+		userService: userService,
 	}
 }
 
 // ensureTasksDir ensures the tasks directory exists
 func (gtm *GitTaskManager) ensureTasksDir() error {
-	if err := os.MkdirAll(gtm.tasksDir, 0755); err != nil {
+	if err := os.MkdirAll(gtm.tasksDir, DefaultFileMode); err != nil {
 		return fmt.Errorf("failed to create tasks directory: %w", err)
 	}
 	return nil
@@ -59,7 +106,7 @@
 func (gtm *GitTaskManager) generateTaskID() string {
 	timestamp := time.Now().Unix()
 	random := uuid.New().String()[:8]
-	return fmt.Sprintf("task-%d-%s", timestamp, random)
+	return fmt.Sprintf("%s%d-%s", TaskIDPrefix, timestamp, random)
 }
 
 // taskToMarkdown converts a Task to markdown format
@@ -95,9 +142,10 @@
 
 	// Build markdown content
 	var content strings.Builder
-	content.WriteString("---\n")
+	content.WriteString(FrontmatterSeparator)
 	content.Write(yamlData)
-	content.WriteString("---\n\n")
+	content.WriteString(FrontmatterSeparator)
+	content.WriteString("\n")
 
 	if task.Description != "" {
 		content.WriteString("# Task Description\n\n")
@@ -111,7 +159,7 @@
 // parseTaskFromMarkdown parses a Task from markdown format
 func (gtm *GitTaskManager) parseTaskFromMarkdown(content string) (*tm.Task, error) {
 	// Split content into frontmatter and body
-	parts := strings.SplitN(content, "---\n", 3)
+	parts := strings.SplitN(content, FrontmatterSeparator, 3)
 	if len(parts) < 3 {
 		return nil, fmt.Errorf("invalid markdown format: missing frontmatter")
 	}
@@ -179,7 +227,7 @@
 
 // readTaskFile reads a task from a file
 func (gtm *GitTaskManager) readTaskFile(taskID string) (*tm.Task, error) {
-	filePath := filepath.Join(gtm.tasksDir, taskID+".md")
+	filePath := filepath.Join(gtm.tasksDir, taskID+TaskFileExt)
 
 	content, err := os.ReadFile(filePath)
 	if err != nil {
@@ -199,8 +247,8 @@
 		return fmt.Errorf("failed to convert task to markdown: %w", err)
 	}
 
-	filePath := filepath.Join(gtm.tasksDir, task.ID+".md")
-	if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
+	filePath := filepath.Join(gtm.tasksDir, task.ID+TaskFileExt)
+	if err := os.WriteFile(filePath, []byte(content), TaskFileMode); err != nil {
 		return fmt.Errorf("failed to write task file: %w", err)
 	}
 
@@ -219,8 +267,8 @@
 
 	var taskFiles []string
 	for _, entry := range entries {
-		if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".md") {
-			taskID := strings.TrimSuffix(entry.Name(), ".md")
+		if !entry.IsDir() && strings.HasSuffix(entry.Name(), TaskFileExt) {
+			taskID := strings.TrimSuffix(entry.Name(), TaskFileExt)
 			taskFiles = append(taskFiles, taskID)
 		}
 	}
@@ -233,7 +281,7 @@
 	ctx := context.Background()
 
 	// Add the task file
-	if err := gtm.git.Add(ctx, []string{filepath.Join(gtm.tasksDir, taskID+".md")}); err != nil {
+	if err := gtm.git.Add(ctx, []string{filepath.Join(gtm.tasksDir, taskID+TaskFileExt)}); err != nil {
 		return fmt.Errorf("failed to add task file: %w", err)
 	}
 
@@ -268,6 +316,13 @@
 	taskID := gtm.generateTaskID()
 	now := time.Now()
 
+	// Get owner name from user service
+	ownerName, err := gtm.userService.GetUserName(req.OwnerID)
+	if err != nil {
+		gtm.logger.Warn("Failed to get owner name, using ID", slog.String("ownerID", req.OwnerID), slog.String("error", err.Error()))
+		ownerName = req.OwnerID
+	}
+
 	// Create task
 	task := &tm.Task{
 		ID:          taskID,
@@ -275,7 +330,7 @@
 		Description: req.Description,
 		Owner: tm.Owner{
 			ID:   req.OwnerID,
-			Name: req.OwnerID, // TODO: Look up owner name from a user service
+			Name: ownerName,
 		},
 		Status:    tm.StatusToDo,
 		Priority:  req.Priority,
@@ -322,7 +377,13 @@
 	}
 	if req.OwnerID != nil {
 		task.Owner.ID = *req.OwnerID
-		task.Owner.Name = *req.OwnerID // TODO: Look up owner name from a user service
+		// Get owner name from user service
+		if ownerName, err := gtm.userService.GetUserName(*req.OwnerID); err == nil {
+			task.Owner.Name = ownerName
+		} else {
+			gtm.logger.Warn("Failed to get owner name, using ID", slog.String("ownerID", *req.OwnerID), slog.String("error", err.Error()))
+			task.Owner.Name = *req.OwnerID
+		}
 		updated = true
 	}
 	if req.Status != nil {