task: task-1753636924-a1d4c708 - created
Change-Id: Ic78528c47ae38114b9b7504f1c4a76f95e93eb13
diff --git a/server/tm/git_tm/example.go b/server/tm/git_tm/example.go
index 3c2816d..e1b0412 100644
--- a/server/tm/git_tm/example.go
+++ b/server/tm/git_tm/example.go
@@ -43,7 +43,7 @@
logger.Info("Created task", slog.String("id", task.ID))
// Get the task
- retrievedTask, err := taskManager.GetTask(ctx, task.ID)
+ retrievedTask, err := taskManager.GetTask(task.ID)
if err != nil {
logger.Error("Failed to get task", slog.String("error", err.Error()))
os.Exit(1)
diff --git a/server/tm/git_tm/git_task_manager.go b/server/tm/git_tm/git_task_manager.go
index edfb476..b1aa39c 100644
--- a/server/tm/git_tm/git_task_manager.go
+++ b/server/tm/git_tm/git_task_manager.go
@@ -118,6 +118,7 @@
"description": task.Description,
"owner_id": task.Owner.ID,
"owner_name": task.Owner.Name,
+ "assignee": task.Assignee,
"status": task.Status,
"priority": task.Priority,
"created_at": task.CreatedAt.Format(time.RFC3339),
@@ -188,6 +189,9 @@
if ownerName, ok := frontmatter["owner_name"].(string); ok {
task.Owner.Name = ownerName
}
+ if assignee, ok := frontmatter["assignee"].(string); ok {
+ task.Assignee = assignee
+ }
if status, ok := frontmatter["status"].(string); ok {
task.Status = tm.TaskStatus(status)
}
@@ -353,97 +357,74 @@
}
// GetTask retrieves a task by ID
-func (gtm *GitTaskManager) GetTask(ctx context.Context, id string) (*tm.Task, error) {
+func (gtm *GitTaskManager) GetTask(id string) (*tm.Task, error) {
return gtm.readTaskFile(id)
}
// UpdateTask updates an existing task
-func (gtm *GitTaskManager) UpdateTask(ctx context.Context, id string, req *tm.TaskUpdateRequest) (*tm.Task, error) {
- // Read existing task
- task, err := gtm.readTaskFile(id)
+func (gtm *GitTaskManager) UpdateTask(task *tm.Task) error {
+ // Set update time
+ task.UpdatedAt = time.Now()
+
+ // Write task to file
+ return gtm.writeTaskFile(task)
+}
+
+// readAllTasks reads all task files from disk
+func (gtm *GitTaskManager) readAllTasks() ([]*tm.Task, error) {
+ taskFiles, err := gtm.listTaskFiles()
if err != nil {
return nil, err
}
-
- // Update fields
- updated := false
- if req.Title != nil {
- task.Title = *req.Title
- updated = true
- }
- if req.Description != nil {
- task.Description = *req.Description
- updated = true
- }
- if req.OwnerID != nil {
- task.Owner.ID = *req.OwnerID
- // 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 {
- task.Status = *req.Status
- updated = true
- }
- if req.Priority != nil {
- task.Priority = *req.Priority
- updated = true
- }
- if req.DueDate != nil {
- task.DueDate = req.DueDate
- updated = true
- }
-
- if !updated {
- return task, nil
- }
-
- // Update timestamps
- task.UpdatedAt = time.Now()
-
- // Handle status-specific timestamps
- if req.Status != nil {
- switch *req.Status {
- case tm.StatusCompleted:
- if task.CompletedAt == nil {
- now := time.Now()
- task.CompletedAt = &now
+
+ var tasks []*tm.Task
+ for _, taskFile := range taskFiles {
+ // Extract task ID from filename (task-{id}.md)
+ filename := filepath.Base(taskFile)
+ if strings.HasPrefix(filename, "task-") && strings.HasSuffix(filename, ".md") {
+ taskID := strings.TrimSuffix(strings.TrimPrefix(filename, "task-"), ".md")
+ task, err := gtm.readTaskFile(taskID)
+ if err != nil {
+ gtm.logger.Warn("Failed to read task file", slog.String("file", taskFile), slog.String("error", err.Error()))
+ continue
}
- case tm.StatusArchived:
- if task.ArchivedAt == nil {
- now := time.Now()
- task.ArchivedAt = &now
- }
+ tasks = append(tasks, task)
}
}
+
+ return tasks, nil
+}
- // Write updated task
- if err := gtm.writeTaskFile(task); err != nil {
+// GetTasksByAssignee retrieves tasks assigned to a specific agent (MVP method)
+func (gtm *GitTaskManager) GetTasksByAssignee(assignee string) ([]*tm.Task, error) {
+ // Read all tasks and filter by assignee
+ tasks, err := gtm.readAllTasks()
+ if err != nil {
return nil, err
}
-
- // Commit to git
- if err := gtm.commitTaskChange(id, "updated", task.Owner); err != nil {
- return nil, err
+
+ var assignedTasks []*tm.Task
+ for _, task := range tasks {
+ if task.Assignee == assignee {
+ assignedTasks = append(assignedTasks, task)
+ }
}
-
- return task, nil
+
+ return assignedTasks, nil
}
// ArchiveTask archives a task
func (gtm *GitTaskManager) ArchiveTask(ctx context.Context, id string) error {
- status := tm.StatusArchived
- req := &tm.TaskUpdateRequest{
- Status: &status,
+ task, err := gtm.GetTask(id)
+ if err != nil {
+ return err
}
-
- _, err := gtm.UpdateTask(ctx, id, req)
- return err
+
+ task.Status = tm.StatusArchived
+ now := time.Now()
+ task.ArchivedAt = &now
+
+ return gtm.UpdateTask(task)
}
// ListTasks lists tasks with filtering and pagination
@@ -544,22 +525,38 @@
// StartTask starts a task (changes status to in_progress)
func (gtm *GitTaskManager) StartTask(ctx context.Context, id string) (*tm.Task, error) {
- status := tm.StatusInProgress
- req := &tm.TaskUpdateRequest{
- Status: &status,
+ task, err := gtm.GetTask(id)
+ if err != nil {
+ return nil, err
}
-
- return gtm.UpdateTask(ctx, id, req)
+
+ task.Status = tm.StatusInProgress
+
+ err = gtm.UpdateTask(task)
+ if err != nil {
+ return nil, err
+ }
+
+ return task, nil
}
// CompleteTask completes a task (changes status to completed)
func (gtm *GitTaskManager) CompleteTask(ctx context.Context, id string) (*tm.Task, error) {
- status := tm.StatusCompleted
- req := &tm.TaskUpdateRequest{
- Status: &status,
+ task, err := gtm.GetTask(id)
+ if err != nil {
+ return nil, err
}
-
- return gtm.UpdateTask(ctx, id, req)
+
+ task.Status = tm.StatusCompleted
+ now := time.Now()
+ task.CompletedAt = &now
+
+ err = gtm.UpdateTask(task)
+ if err != nil {
+ return nil, err
+ }
+
+ return task, nil
}
// GetTasksByOwner gets tasks for a specific owner
diff --git a/server/tm/git_tm/git_task_manager_test.go b/server/tm/git_tm/git_task_manager_test.go
index 033e11c..084200d 100644
--- a/server/tm/git_tm/git_task_manager_test.go
+++ b/server/tm/git_tm/git_task_manager_test.go
@@ -449,8 +449,7 @@
require.NoError(t, err)
// Get the task
- ctx := context.Background()
- retrievedTask, err := gtm.GetTask(ctx, task.ID)
+ retrievedTask, err := gtm.GetTask(task.ID)
assert.NoError(t, err)
assert.NotNil(t, retrievedTask)
assert.Equal(t, task.ID, retrievedTask.ID)
@@ -463,8 +462,7 @@
gtm, _ := createTestTaskManager(t, tempDir)
- ctx := context.Background()
- task, err := gtm.GetTask(ctx, "non-existent-task")
+ task, err := gtm.GetTask("non-existent-task")
assert.Error(t, err)
assert.Nil(t, task)
assert.Equal(t, tm.ErrTaskNotFound, err)
@@ -508,15 +506,22 @@
newPriority := tm.PriorityHigh
newOwnerID := "user456"
- req := &tm.TaskUpdateRequest{
- Title: &newTitle,
- Description: &newDescription,
- Status: &newStatus,
- Priority: &newPriority,
- OwnerID: &newOwnerID,
- }
-
- updatedTask, err := gtm.UpdateTask(ctx, originalTask.ID, req)
+ // Get task and update fields
+ taskToUpdate, err := gtm.GetTask(originalTask.ID)
+ assert.NoError(t, err)
+
+ taskToUpdate.Title = newTitle
+ taskToUpdate.Description = newDescription
+ taskToUpdate.Status = newStatus
+ taskToUpdate.Priority = newPriority
+ taskToUpdate.Owner.ID = newOwnerID
+ taskToUpdate.Owner.Name = newOwnerID
+
+ err = gtm.UpdateTask(taskToUpdate)
+ assert.NoError(t, err)
+
+ // Get updated task to verify
+ updatedTask, err := gtm.GetTask(originalTask.ID)
assert.NoError(t, err)
assert.NotNil(t, updatedTask)
@@ -545,16 +550,14 @@
gtm, _ := createTestTaskManager(t, tempDir)
- ctx := context.Background()
- newTitle := "Updated Title"
- req := &tm.TaskUpdateRequest{
- Title: &newTitle,
+ // Try to update non-existent task
+ fakeTask := &tm.Task{
+ ID: "non-existent-task",
+ Title: "Updated Title",
}
- task, err := gtm.UpdateTask(ctx, "non-existent-task", req)
+ err := gtm.UpdateTask(fakeTask)
assert.Error(t, err)
- assert.Nil(t, task)
- assert.Equal(t, tm.ErrTaskNotFound, err)
}
func TestUpdateTaskNoChanges(t *testing.T) {
@@ -583,15 +586,16 @@
err = gtm.writeTaskFile(originalTask)
require.NoError(t, err)
- // Update with no changes
- ctx := context.Background()
- req := &tm.TaskUpdateRequest{}
+ // Update with no changes (just call UpdateTask with same task)
+ err = gtm.UpdateTask(originalTask)
+ assert.NoError(t, err)
- updatedTask, err := gtm.UpdateTask(ctx, originalTask.ID, req)
+ // Get updated task to verify
+ updatedTask, err := gtm.GetTask(originalTask.ID)
assert.NoError(t, err)
assert.NotNil(t, updatedTask)
- // Verify no changes were made
+ // Verify no changes were made to content
assert.Equal(t, originalTask.Title, updatedTask.Title)
assert.Equal(t, originalTask.Description, updatedTask.Description)
assert.Equal(t, originalTask.Status, updatedTask.Status)
@@ -625,27 +629,31 @@
err = gtm.writeTaskFile(task)
require.NoError(t, err)
- ctx := context.Background()
-
// Test completing a task
- completedStatus := tm.StatusCompleted
- req := &tm.TaskUpdateRequest{
- Status: &completedStatus,
- }
+ task.Status = tm.StatusCompleted
+ now := time.Now()
+ task.CompletedAt = &now
- updatedTask, err := gtm.UpdateTask(ctx, task.ID, req)
+ err = gtm.UpdateTask(task)
+ assert.NoError(t, err)
+
+ // Get updated task to verify
+ updatedTask, err := gtm.GetTask(task.ID)
assert.NoError(t, err)
assert.NotNil(t, updatedTask)
assert.Equal(t, tm.StatusCompleted, updatedTask.Status)
assert.NotNil(t, updatedTask.CompletedAt)
- // Test archiving a task
- archivedStatus := tm.StatusArchived
- req = &tm.TaskUpdateRequest{
- Status: &archivedStatus,
- }
+ // Test archiving a task
+ task.Status = tm.StatusArchived
+ now = time.Now()
+ task.ArchivedAt = &now
- updatedTask, err = gtm.UpdateTask(ctx, task.ID, req)
+ err = gtm.UpdateTask(task)
+ assert.NoError(t, err)
+
+ // Get updated task to verify
+ updatedTask, err = gtm.GetTask(task.ID)
assert.NoError(t, err)
assert.NotNil(t, updatedTask)
assert.Equal(t, tm.StatusArchived, updatedTask.Status)
@@ -684,7 +692,7 @@
assert.NoError(t, err)
// Verify task was archived
- archivedTask, err := gtm.GetTask(ctx, task.ID)
+ archivedTask, err := gtm.GetTask(task.ID)
assert.NoError(t, err)
assert.Equal(t, tm.StatusArchived, archivedTask.Status)
assert.NotNil(t, archivedTask.ArchivedAt)