Update logging

Change-Id: I13279582aa717edad5d56323866b941db1919404
diff --git a/server/agent/agent.go b/server/agent/agent.go
index 6de4784..ed4706d 100644
--- a/server/agent/agent.go
+++ b/server/agent/agent.go
@@ -3,7 +3,7 @@
 import (
 	"context"
 	"fmt"
-	"log"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"strings"
@@ -11,6 +11,7 @@
 
 	"github.com/iomodo/staff/git"
 	"github.com/iomodo/staff/llm"
+	_ "github.com/iomodo/staff/llm/openai" // Import for side effects (registers provider)
 	"github.com/iomodo/staff/tm"
 )
 
@@ -58,10 +59,11 @@
 	gitInterface git.GitInterface
 	ctx          context.Context
 	cancel       context.CancelFunc
+	logger       *slog.Logger
 }
 
 // NewAgent creates a new agent instance
-func NewAgent(config AgentConfig) (*Agent, error) {
+func NewAgent(config AgentConfig, logger *slog.Logger) (*Agent, error) {
 	// Validate configuration
 	if err := validateConfig(config); err != nil {
 		return nil, fmt.Errorf("invalid config: %w", err)
@@ -89,7 +91,7 @@
 			Timeout:             30 * time.Second,
 			PullRequestProvider: gerritPRProvider,
 		}
-		gitInterface = git.NewGitWithPullRequests(config.GitRepoPath, gitConfig, gerritPRProvider)
+		gitInterface = git.NewGitWithPullRequests(config.GitRepoPath, gitConfig, gerritPRProvider, logger)
 	} else {
 		// Use default git interface (GitHub)
 		gitInterface = git.DefaultGit(config.GitRepoPath)
@@ -104,6 +106,7 @@
 		gitInterface: gitInterface,
 		ctx:          ctx,
 		cancel:       cancel,
+		logger:       logger,
 	}
 
 	return agent, nil
@@ -134,8 +137,8 @@
 
 // Run starts the agent's main loop
 func (a *Agent) Run() error {
-	log.Printf("Starting agent %s (%s)", a.Config.Name, a.Config.Role)
-	defer log.Printf("Agent %s stopped", a.Config.Name)
+	a.logger.Info("Starting agent", slog.String("name", a.Config.Name), slog.String("role", a.Config.Role))
+	defer a.logger.Info("Agent stopped", slog.String("name", a.Config.Name))
 
 	// Initialize git repository if needed
 	if err := a.initializeGit(); err != nil {
@@ -149,7 +152,7 @@
 			return a.ctx.Err()
 		default:
 			if err := a.processNextTask(); err != nil {
-				log.Printf("Error processing task: %v", err)
+				a.logger.Error("Error processing task", slog.String("error", err.Error()))
 				// Continue running even if there's an error
 				time.Sleep(30 * time.Second)
 			}
@@ -159,7 +162,7 @@
 
 // Stop stops the agent
 func (a *Agent) Stop() {
-	log.Printf("Stopping agent %s", a.Config.Name)
+	a.logger.Info("Stopping agent", slog.String("name", a.Config.Name))
 	a.cancel()
 	if a.llmProvider != nil {
 		a.llmProvider.Close()
@@ -248,7 +251,7 @@
 				}
 			}
 		} else {
-			log.Printf("Already on target branch: %s", a.Config.GitBranch)
+			a.logger.Info("Already on target branch", slog.String("branch", a.Config.GitBranch))
 		}
 	}
 
@@ -280,7 +283,7 @@
 		return nil
 	}
 
-	log.Printf("Processing task: %s - %s", taskToProcess.ID, taskToProcess.Title)
+	a.logger.Info("Processing task", slog.String("id", taskToProcess.ID), slog.String("title", taskToProcess.Title))
 
 	// Start the task
 	startedTask, err := a.Config.TaskManager.StartTask(ctx, taskToProcess.ID)
@@ -292,7 +295,7 @@
 	solution, err := a.processTaskWithLLM(startedTask)
 	if err != nil {
 		// Mark task as failed or retry
-		log.Printf("Failed to process task with LLM: %v", err)
+		a.logger.Error("Failed to process task with LLM", slog.String("error", err.Error()))
 		return err
 	}
 
@@ -306,7 +309,7 @@
 		return fmt.Errorf("failed to complete task: %w", err)
 	}
 
-	log.Printf("Successfully completed task: %s", startedTask.ID)
+	a.logger.Info("Successfully completed task", slog.String("id", startedTask.ID))
 	return nil
 }
 
@@ -416,7 +419,7 @@
 		if err := a.gitInterface.Push(ctx, "origin", gerritRef, git.PushOptions{}); err != nil {
 			return fmt.Errorf("failed to push to Gerrit: %w", err)
 		}
-		log.Printf("Created Gerrit change for task %s by pushing to %s", task.ID, gerritRef)
+		a.logger.Info("Created Gerrit change for task", slog.String("id", task.ID), slog.String("ref", gerritRef))
 	} else {
 		// For GitHub: Push branch and create PR
 		if err := a.gitInterface.Push(ctx, "origin", branchName, git.PushOptions{SetUpstream: true}); err != nil {
@@ -438,7 +441,7 @@
 			return fmt.Errorf("failed to create pull request: %w", err)
 		}
 
-		log.Printf("Created pull request for task %s: %s (ID: %s)", task.ID, pr.Title, pr.ID)
+		a.logger.Info("Created pull request for task", slog.String("id", task.ID), slog.String("title", pr.Title), slog.String("pr_id", pr.ID))
 	}
 
 	return nil
diff --git a/server/agent/agent_test.go b/server/agent/agent_test.go
index 405e5b7..6ec2adc 100644
--- a/server/agent/agent_test.go
+++ b/server/agent/agent_test.go
@@ -2,6 +2,7 @@
 
 import (
 	"context"
+	"log/slog"
 	"os"
 	"path/filepath"
 	"testing"
@@ -104,8 +105,11 @@
 	err = gitInterface.SetUserConfig(ctx, userConfig)
 	require.NoError(t, err)
 
+	// Create logger for testing
+	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
 	// Create task manager
-	taskManager := git_tm.NewGitTaskManager(gitInterface, tasksDir)
+	taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, tasksDir, logger)
 
 	// Create LLM config (using a mock configuration)
 	llmConfig := llm.Config{
@@ -132,6 +136,9 @@
 		GitBranch:    "main",
 	}
 
+	// Create logger for testing
+	logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
 	// Create agent with mock LLM provider
 	agent := &Agent{
 		Config:       config,
@@ -139,6 +146,7 @@
 		gitInterface: git.DefaultGit(codeRepoDir),
 		ctx:          context.Background(),
 		cancel:       func() {},
+		logger:       logger,
 	}
 
 	cleanup := func() {
@@ -150,8 +158,73 @@
 }
 
 func TestNewAgent(t *testing.T) {
-	agent, cleanup := setupTestAgent(t)
-	defer cleanup()
+	// Create temporary directories
+	tempDir, err := os.MkdirTemp("", "agent-test")
+	require.NoError(t, err)
+	defer os.RemoveAll(tempDir)
+
+	tasksDir := filepath.Join(tempDir, "tasks")
+	workspaceDir := filepath.Join(tempDir, "workspace")
+	codeRepoDir := filepath.Join(tempDir, "code-repo")
+
+	// Create directories
+	require.NoError(t, os.MkdirAll(tasksDir, 0755))
+	require.NoError(t, os.MkdirAll(workspaceDir, 0755))
+	require.NoError(t, os.MkdirAll(codeRepoDir, 0755))
+
+	// Initialize git repositories
+	gitInterface := git.DefaultGit(tasksDir)
+	ctx := context.Background()
+
+	err = gitInterface.Init(ctx, tasksDir)
+	require.NoError(t, err)
+
+	// Set git user config
+	userConfig := git.UserConfig{
+		Name:  "Test User",
+		Email: "test@example.com",
+	}
+	err = gitInterface.SetUserConfig(ctx, userConfig)
+	require.NoError(t, err)
+
+	// Create logger for testing
+	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
+	// Create task manager
+	taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, tasksDir, logger)
+
+	// Create LLM config (using a mock configuration)
+	llmConfig := llm.Config{
+		Provider: llm.ProviderOpenAI,
+		APIKey:   "test-key",
+		BaseURL:  "https://api.openai.com/v1",
+		Timeout:  30 * time.Second,
+	}
+
+	// Create agent config
+	config := AgentConfig{
+		Name:         "test-agent",
+		Role:         "Test Engineer",
+		GitUsername:  "test-agent",
+		GitEmail:     "test-agent@test.com",
+		WorkingDir:   workspaceDir,
+		LLMProvider:  llm.ProviderOpenAI,
+		LLMModel:     "gpt-3.5-turbo",
+		LLMConfig:    llmConfig,
+		SystemPrompt: "You are a test agent. Provide simple, clear solutions.",
+		TaskManager:  taskManager,
+		GitRepoPath:  codeRepoDir,
+		GitRemote:    "origin",
+		GitBranch:    "main",
+	}
+
+	// Create logger for testing
+	logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
+	// Create agent using NewAgent function
+	agent, err := NewAgent(config, logger)
+	require.NoError(t, err)
+	defer agent.Stop()
 
 	assert.NotNil(t, agent)
 	assert.Equal(t, "test-agent", agent.Config.Name)
diff --git a/server/agent/example.go b/server/agent/example.go
index 1233bdc..a7faea9 100644
--- a/server/agent/example.go
+++ b/server/agent/example.go
@@ -2,7 +2,8 @@
 
 import (
 	"context"
-	"log"
+	"log/slog"
+	"os"
 	"time"
 
 	"github.com/iomodo/staff/git"
@@ -13,11 +14,14 @@
 
 // ExampleAgent demonstrates how to create and run an agent
 func ExampleAgent() {
+	// Create logger
+	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
 	// Create git interface for task management
 	gitInterface := git.DefaultGit("./tasks-repo")
 
 	// Create task manager
-	taskManager := git_tm.NewGitTaskManager(gitInterface, "./tasks-repo")
+	taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, "./tasks-repo", logger)
 
 	// Create LLM configuration
 	llmConfig := llm.Config{
@@ -57,9 +61,10 @@
 	}
 
 	// Create agent
-	agent, err := NewAgent(config)
+	agent, err := NewAgent(config, logger)
 	if err != nil {
-		log.Fatalf("Failed to create agent: %v", err)
+		logger.Error("Failed to create agent", slog.String("error", err.Error()))
+		os.Exit(1)
 	}
 
 	// Create a sample task
@@ -71,15 +76,16 @@
 		Priority:    tm.PriorityHigh,
 	})
 	if err != nil {
-		log.Fatalf("Failed to create task: %v", err)
+		logger.Error("Failed to create task", slog.String("error", err.Error()))
+		os.Exit(1)
 	}
 
-	log.Printf("Created task: %s", task.ID)
+	logger.Info("Created task", slog.String("id", task.ID))
 
 	// Run the agent (this will process tasks in an infinite loop)
 	go func() {
 		if err := agent.Run(); err != nil {
-			log.Printf("Agent stopped with error: %v", err)
+			logger.Error("Agent stopped with error", slog.String("error", err.Error()))
 		}
 	}()
 
@@ -92,9 +98,12 @@
 
 // ExampleMultipleAgents demonstrates how to create multiple agents with different roles
 func ExampleMultipleAgents() {
+	// Create logger
+	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
+
 	// Create shared git interface for task management
 	gitInterface := git.DefaultGit("./tasks-repo")
-	taskManager := git_tm.NewGitTaskManager(gitInterface, "./tasks-repo")
+	taskManager := git_tm.NewGitTaskManagerWithLogger(gitInterface, "./tasks-repo", logger)
 
 	// Create agents with different roles
 	agents := []AgentConfig{
@@ -177,16 +186,16 @@
 
 	// Create and start all agents
 	for _, config := range agents {
-		agent, err := NewAgent(config)
+		agent, err := NewAgent(config, logger)
 		if err != nil {
-			log.Printf("Failed to create agent %s: %v", config.Name, err)
+			logger.Error("Failed to create agent", slog.String("name", config.Name), slog.String("error", err.Error()))
 			continue
 		}
 
 		go func(agent *Agent, name string) {
-			log.Printf("Starting agent: %s", name)
+			logger.Info("Starting agent", slog.String("name", name))
 			if err := agent.Run(); err != nil {
-				log.Printf("Agent %s stopped with error: %v", name, err)
+				logger.Error("Agent stopped with error", slog.String("name", name), slog.String("error", err.Error()))
 			}
 		}(agent, config.Name)
 	}