workflow.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package lunatask
  6
  7import (
  8	"errors"
  9	"fmt"
 10	"strings"
 11)
 12
 13// Workflow represents an area's task management workflow.
 14type Workflow string
 15
 16// Valid workflow values.
 17const (
 18	WorkflowPriorityList   Workflow = "priority_list"
 19	WorkflowNowLater       Workflow = "now_later"
 20	WorkflowKanban         Workflow = "kanban"
 21	WorkflowPlanYourDays   Workflow = "plan_your_days"
 22	WorkflowMustShouldWant Workflow = "must_should_want"
 23	WorkflowEisenhower     Workflow = "eisenhower"
 24)
 25
 26// Errors returned by Workflow operations.
 27var (
 28	// ErrInvalidWorkflow is returned when parsing an unknown workflow string.
 29	ErrInvalidWorkflow = errors.New("invalid workflow")
 30)
 31
 32// String returns the workflow value as a string.
 33func (w Workflow) String() string {
 34	return string(w)
 35}
 36
 37// ValidStatuses returns the task statuses that apply to this workflow.
 38func (w Workflow) ValidStatuses() []TaskStatus {
 39	switch w {
 40	case WorkflowPriorityList:
 41		return nil
 42	case WorkflowNowLater:
 43		return []TaskStatus{StatusLater, StatusInProgress, StatusCompleted}
 44	case WorkflowKanban:
 45		return []TaskStatus{StatusLater, StatusNext, StatusInProgress, StatusWaiting, StatusCompleted}
 46	case WorkflowPlanYourDays:
 47		return []TaskStatus{StatusCompleted}
 48	case WorkflowMustShouldWant:
 49		return []TaskStatus{StatusCompleted}
 50	case WorkflowEisenhower:
 51		return []TaskStatus{StatusCompleted}
 52	default:
 53		return nil
 54	}
 55}
 56
 57// UsesMotivation reports whether this workflow uses the motivation field (must/should/want).
 58func (w Workflow) UsesMotivation() bool {
 59	return w == WorkflowMustShouldWant
 60}
 61
 62// UsesEisenhower reports whether this workflow uses the important/urgent fields.
 63func (w Workflow) UsesEisenhower() bool {
 64	return w == WorkflowEisenhower
 65}
 66
 67// UsesScheduling reports whether this workflow is date-oriented (scheduled_on).
 68func (w Workflow) UsesScheduling() bool {
 69	return w == WorkflowPlanYourDays
 70}
 71
 72// UsesPriority reports whether this workflow uses only priority (no status columns).
 73func (w Workflow) UsesPriority() bool {
 74	return w == WorkflowPriorityList
 75}
 76
 77// Description returns a human-readable description of the workflow for LLMs.
 78func (w Workflow) Description() string {
 79	switch w {
 80	case WorkflowPriorityList:
 81		return "Priority-only workflow. Tasks are ranked by priority (lowest to highest) without status columns."
 82	case WorkflowNowLater:
 83		return "Simple two-column workflow. Tasks are either 'later' or 'in-progress', then marked 'completed'."
 84	case WorkflowKanban:
 85		return "Full kanban board with columns: later, next, in-progress, waiting, completed."
 86	case WorkflowPlanYourDays:
 87		return "Date-oriented workflow. Tasks are scheduled for specific days using the scheduled_on field."
 88	case WorkflowMustShouldWant:
 89		return "Motivation-based workflow. Tasks are categorized as 'must', 'should', or 'want' to clarify why they matter."
 90	case WorkflowEisenhower:
 91		return "Eisenhower matrix workflow. Tasks are categorized by 'important' and 'urgent' flags into four quadrants."
 92	default:
 93		return fmt.Sprintf("Unknown workflow: %s", w)
 94	}
 95}
 96
 97// ParseWorkflow parses a string to a Workflow value (case-insensitive).
 98// Accepts both snake_case (priority_list) and kebab-case (priority-list).
 99func ParseWorkflow(str string) (Workflow, error) {
100	normalized := strings.ToLower(strings.ReplaceAll(str, "-", "_"))
101	switch normalized {
102	case "priority_list":
103		return WorkflowPriorityList, nil
104	case "now_later":
105		return WorkflowNowLater, nil
106	case "kanban":
107		return WorkflowKanban, nil
108	case "plan_your_days":
109		return WorkflowPlanYourDays, nil
110	case "must_should_want":
111		return WorkflowMustShouldWant, nil
112	case "eisenhower":
113		return WorkflowEisenhower, nil
114	default:
115		return "", fmt.Errorf("%w: %q", ErrInvalidWorkflow, str)
116	}
117}
118
119// Workflows returns all valid workflow values.
120func Workflows() []Workflow {
121	return []Workflow{
122		WorkflowPriorityList,
123		WorkflowNowLater,
124		WorkflowKanban,
125		WorkflowPlanYourDays,
126		WorkflowMustShouldWant,
127		WorkflowEisenhower,
128	}
129}