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}