rdev/cmd/sdlc/cmd_task.go
jordan 56e3f83955 feat: add auth scopes, OpenAPI docs, SDLC guides, and code quality improvements
- Add auth.RequireScope() to all handler routes for proper authorization
- Add SDLC OpenAPI endpoint documentation (state, features, tasks, branches, merge, archive, orchestrator)
- Add SDLC documentation guides (getting-started, cli-reference, api-reference, command-catalog)
- Add artifact_test.go for SDLC artifact coverage
- Add CLAUDE.md rules: auth scopes requirement, error wrapping with %w
- Fix error wrapping to use %w instead of %v throughout codebase
- Improve CLI merge command with conflict detection and resolution
- Fix handler tests to include auth middleware for RequireScope
- Add cookbook tree runner scripts for automated testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:55:50 -07:00

203 lines
4.1 KiB
Go

package main
import (
"fmt"
"github.com/orchard9/rdev/internal/sdlc"
"github.com/spf13/cobra"
)
var taskCmd = &cobra.Command{
Use: "task",
Short: "Manage feature tasks",
}
var taskListCmd = &cobra.Command{
Use: "list <feature>",
Short: "List tasks for a feature",
Args: cobra.ExactArgs(1),
RunE: func(_ *cobra.Command, args []string) error {
root := mustResolveRoot()
f, err := sdlc.LoadFeature(root, args[0])
if err != nil {
return err
}
if jsonOutput {
return printJSON(f.Tasks)
}
if len(f.Tasks) == 0 {
fmt.Println("No tasks defined.")
fmt.Printf("Add one: sdlc task add %s \"Task title\"\n", args[0])
return nil
}
summary := sdlc.SummarizeTasks(f.Tasks)
fmt.Printf("Tasks for %s (%d/%d complete):\n", f.Slug, summary.Completed, summary.Total)
for _, t := range f.Tasks {
icon := "○"
switch t.Status {
case sdlc.TaskComplete:
icon = "✓"
case sdlc.TaskInProgress:
icon = "→"
case sdlc.TaskBlocked:
icon = "✗"
}
fmt.Printf(" %s %s: %s [%s]\n", icon, t.ID, t.Title, t.Status)
}
return nil
},
}
var taskStartCmd = &cobra.Command{
Use: "start <feature> <task-id>",
Short: "Mark a task as in-progress",
Args: cobra.ExactArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
root := mustResolveRoot()
slug, taskID := args[0], args[1]
f, err := sdlc.LoadFeature(root, slug)
if err != nil {
return err
}
f.Tasks, err = sdlc.StartTask(f.Tasks, taskID)
if err != nil {
return err
}
f.UpdateTaskSummary()
if err := f.Save(root); err != nil {
return err
}
if jsonOutput {
return printJSON(map[string]string{"feature": slug, "task": taskID, "status": "in_progress"})
}
fmt.Printf("Started: %s/%s\n", slug, taskID)
return nil
},
}
var taskCompleteCmd = &cobra.Command{
Use: "complete <feature> <task-id>",
Short: "Mark a task as complete",
Args: cobra.ExactArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
root := mustResolveRoot()
slug, taskID := args[0], args[1]
f, err := sdlc.LoadFeature(root, slug)
if err != nil {
return err
}
f.Tasks, err = sdlc.CompleteTask(f.Tasks, taskID)
if err != nil {
return err
}
f.UpdateTaskSummary()
if err := f.Save(root); err != nil {
return err
}
// Record in state
state, err := sdlc.LoadState(root)
if err != nil {
return err
}
state.RecordAction("COMPLETE_TASK", slug, "cli", "success")
if err := state.Save(root); err != nil {
return err
}
if jsonOutput {
return printJSON(map[string]string{"feature": slug, "task": taskID, "status": "complete"})
}
s := sdlc.SummarizeTasks(f.Tasks)
fmt.Printf("Completed: %s/%s (%d/%d tasks done)\n", slug, taskID, s.Completed, s.Total)
return nil
},
}
var taskBlockCmd = &cobra.Command{
Use: "block <feature> <task-id>",
Short: "Mark a task as blocked",
Args: cobra.ExactArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
root := mustResolveRoot()
slug, taskID := args[0], args[1]
f, err := sdlc.LoadFeature(root, slug)
if err != nil {
return err
}
f.Tasks, err = sdlc.BlockTask(f.Tasks, taskID)
if err != nil {
return err
}
f.UpdateTaskSummary()
if err := f.Save(root); err != nil {
return err
}
if jsonOutput {
return printJSON(map[string]string{"feature": slug, "task": taskID, "status": "blocked"})
}
fmt.Printf("Blocked: %s/%s\n", slug, taskID)
return nil
},
}
var taskAddCmd = &cobra.Command{
Use: "add <feature> <title>",
Short: "Add a new task",
Args: cobra.ExactArgs(2),
RunE: func(_ *cobra.Command, args []string) error {
root := mustResolveRoot()
slug, title := args[0], args[1]
f, err := sdlc.LoadFeature(root, slug)
if err != nil {
return err
}
f.Tasks = sdlc.AddTask(f.Tasks, title)
f.UpdateTaskSummary()
if err := f.Save(root); err != nil {
return err
}
newTask := f.Tasks[len(f.Tasks)-1]
if jsonOutput {
return printJSON(newTask)
}
fmt.Printf("Added: %s/%s - %s\n", slug, newTask.ID, title)
return nil
},
}
func init() {
taskCmd.AddCommand(
taskListCmd,
taskStartCmd,
taskCompleteCmd,
taskBlockCmd,
taskAddCmd,
)
rootCmd.AddCommand(taskCmd)
}