summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Omni/Jr/Web.hs16
-rw-r--r--Omni/Jr/Web/Style.hs6
-rw-r--r--Omni/Task.hs24
-rw-r--r--Omni/Task/Core.hs17
4 files changed, 37 insertions, 26 deletions
diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs
index 2e4ee66..8508560 100644
--- a/Omni/Jr/Web.hs
+++ b/Omni/Jr/Web.hs
@@ -680,6 +680,7 @@ statusBadge status =
TaskCore.Review -> ("badge badge-review", "Review")
TaskCore.Approved -> ("badge badge-approved", "Approved")
TaskCore.Done -> ("badge badge-done", "Done")
+ TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
in Lucid.span_ [Lucid.class_ cls] label
complexityBadge :: (Monad m) => Int -> Lucid.HtmlT m ()
@@ -770,6 +771,7 @@ clickableBadge status _tid =
TaskCore.Review -> ("badge badge-review status-badge-clickable", "Review")
TaskCore.Approved -> ("badge badge-approved status-badge-clickable", "Approved")
TaskCore.Done -> ("badge badge-done status-badge-clickable", "Done")
+ TaskCore.NeedsHelp -> ("badge badge-needshelp status-badge-clickable", "Needs Help")
in Lucid.span_
[ Lucid.class_ cls,
Lucid.tabindex_ "0",
@@ -797,6 +799,7 @@ statusDropdownOptions currentStatus tid =
statusOption TaskCore.Review currentStatus tid
statusOption TaskCore.Approved currentStatus tid
statusOption TaskCore.Done currentStatus tid
+ statusOption TaskCore.NeedsHelp currentStatus tid
statusOption :: (Monad m) => TaskCore.Status -> TaskCore.Status -> Text -> Lucid.HtmlT m ()
statusOption opt currentStatus tid =
@@ -807,6 +810,7 @@ statusOption opt currentStatus tid =
TaskCore.Review -> ("badge badge-review", "Review")
TaskCore.Approved -> ("badge badge-approved", "Approved")
TaskCore.Done -> ("badge badge-done", "Done")
+ TaskCore.NeedsHelp -> ("badge badge-needshelp", "Needs Help")
isSelected = opt == currentStatus
optClass = cls <> " status-dropdown-option" <> if isSelected then " selected" else ""
in Lucid.form_
@@ -1083,8 +1087,8 @@ instance Lucid.ToHtml InterventionPage where
let crumbs = [Breadcrumb "Jr" (Just "/"), Breadcrumb "Needs Human Action" Nothing]
failed = TaskCore.failedTasks actionItems
epicsReady = TaskCore.epicsInReview actionItems
- human = TaskCore.humanTasks actionItems
- totalCount = length failed + length epicsReady + length human
+ needsHelp = TaskCore.tasksNeedingHelp actionItems
+ totalCount = length failed + length epicsReady + length needsHelp
in Lucid.doctypehtml_ <| do
pageHead "Needs Human Action - Jr"
pageBodyWithCrumbs crumbs <| do
@@ -1103,10 +1107,10 @@ instance Lucid.ToHtml InterventionPage where
Lucid.h2_ [Lucid.class_ "section-header"] <| Lucid.toHtml ("Epics Ready for Review (" <> tshow (length epicsReady) <> ")")
Lucid.p_ [Lucid.class_ "info-msg"] "Epics with all children completed. Verify before closing."
Lucid.div_ [Lucid.class_ "task-list"] <| traverse_ renderEpicReviewCard epicsReady
- unless (null human) <| do
- Lucid.h2_ [Lucid.class_ "section-header"] <| Lucid.toHtml ("Human Tasks (" <> tshow (length human) <> ")")
- Lucid.p_ [Lucid.class_ "info-msg"] "Tasks explicitly marked as needing human work."
- Lucid.div_ [Lucid.class_ "task-list"] <| traverse_ renderTaskCard (sortTasks currentSort human)
+ unless (null needsHelp) <| do
+ Lucid.h2_ [Lucid.class_ "section-header"] <| Lucid.toHtml ("Needs Help (" <> tshow (length needsHelp) <> ")")
+ Lucid.p_ [Lucid.class_ "info-msg"] "Tasks where Jr needs human guidance or decisions."
+ Lucid.div_ [Lucid.class_ "task-list"] <| traverse_ renderTaskCard (sortTasks currentSort needsHelp)
renderEpicReviewCard :: (Monad m) => TaskCore.EpicForReview -> Lucid.HtmlT m ()
renderEpicReviewCard epicReview = do
diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs
index 08fda5d..9a0c12d 100644
--- a/Omni/Jr/Web/Style.hs
+++ b/Omni/Jr/Web/Style.hs
@@ -584,6 +584,9 @@ statusBadges = do
".badge-done" ? do
backgroundColor "#d1fae5"
color "#065f46"
+ ".badge-needshelp" ? do
+ backgroundColor "#fef3c7"
+ color "#92400e"
".status-badge-dropdown" ? do
position relative
display inlineBlock
@@ -1864,6 +1867,9 @@ darkModeStyles =
".badge-done" ? do
backgroundColor "#064e3b"
color "#6ee7b7"
+ ".badge-needshelp" ? do
+ backgroundColor "#78350f"
+ color "#fcd34d"
".badge-p0" ? do
backgroundColor "#7f1d1d"
color "#fca5a5"
diff --git a/Omni/Task.hs b/Omni/Task.hs
index ce26f41..1385a4b 100644
--- a/Omni/Task.hs
+++ b/Omni/Task.hs
@@ -85,11 +85,11 @@ Commands:
Options:
-h --help Show this help
--title=<title> Task title
- --type=<type> Task type: epic, task, or human (default: task)
+ --type=<type> Task type: epic or task (default: task)
--parent=<id> Parent epic ID
--priority=<p> Priority: 0-4 (0=critical, 4=backlog, default: 2)
--complexity=<c> Complexity: 1-5 for model selection (1=trivial, 5=expert)
- --status=<status> Filter by status: draft, open, in-progress, review, approved, done
+ --status=<status> Filter by status: draft, open, in-progress, review, approved, done, needs-help
--epic=<id> Filter stats by epic (recursive)
--deps=<ids> Comma-separated list of dependency IDs
--dep-type=<type> Dependency type: blocks, discovered-from, parent-child, related
@@ -109,7 +109,7 @@ Options:
Arguments:
<title> Task title
<id> Task ID
- <status> Task status (draft, open, in-progress, review, approved, done)
+ <status> Task status (draft, open, in-progress, review, approved, done, needs-help)
<message> Comment message
<file> JSONL file to import
|]
@@ -147,8 +147,7 @@ move' args
Nothing -> pure WorkTask
Just "epic" -> pure Epic
Just "task" -> pure WorkTask
- Just "human" -> pure HumanTask
- Just other -> panic <| "Invalid task type: " <> T.pack other <> ". Use: epic, task, or human"
+ Just other -> panic <| "Invalid task type: " <> T.pack other <> ". Use: epic or task"
parent <- case Cli.getArg args (Cli.longOption "parent") of
Nothing -> pure Nothing
Just p -> pure <| Just (T.pack p)
@@ -295,7 +294,6 @@ move' args
Nothing -> pure Nothing
Just "epic" -> pure <| Just Epic
Just "task" -> pure <| Just WorkTask
- Just "human" -> pure <| Just HumanTask
Just other -> panic <| "Invalid task type: " <> T.pack other
maybeParent <- case Cli.getArg args (Cli.longOption "parent") of
Nothing -> pure Nothing
@@ -308,7 +306,8 @@ move' args
Just "review" -> pure <| Just Review
Just "approved" -> pure <| Just Approved
Just "done" -> pure <| Just Done
- Just other -> panic <| "Invalid status: " <> T.pack other <> ". Use: draft, open, in-progress, review, approved, or done"
+ Just "needs-help" -> pure <| Just NeedsHelp
+ Just other -> panic <| "Invalid status: " <> T.pack other <> ". Use: draft, open, in-progress, review, approved, done, or needs-help"
maybeNamespace <- case Cli.getArg args (Cli.longOption "namespace") of
Nothing -> pure Nothing
Just ns -> do
@@ -362,7 +361,8 @@ move' args
"review" -> Review
"approved" -> Approved
"done" -> Done
- _ -> panic "Invalid status. Use: draft, open, in-progress, review, approved, or done"
+ "needs-help" -> NeedsHelp
+ _ -> panic "Invalid status. Use: draft, open, in-progress, review, approved, done, or needs-help"
-- Show verification checklist warning when marking Done without --verified
when (newStatus == Done && not isVerified && not (isJsonMode args)) <| do
@@ -620,11 +620,9 @@ unitTests =
taskStatus task Test.@?= Open
taskPriority task Test.@?= P2
null (taskDependencies task) Test.@?= True,
- Test.unit "can create human task" <| do
- task <- createTask "Human Task" HumanTask Nothing Nothing P2 Nothing [] "Human task description"
- taskType task Test.@?= HumanTask,
- Test.unit "ready tasks exclude human tasks" <| do
- task <- createTask "Human Task" HumanTask Nothing Nothing P2 Nothing [] "Human task"
+ Test.unit "ready tasks exclude NeedsHelp tasks" <| do
+ task <- createTask "Needs Help Task" WorkTask Nothing Nothing P2 Nothing [] "Task needing help"
+ updateTaskStatus (taskId task) NeedsHelp []
ready <- getReadyTasks
(taskId task `notElem` map taskId ready) Test.@?= True,
Test.unit "ready tasks exclude draft tasks" <| do
diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs
index 35f3ea7..8badf6b 100644
--- a/Omni/Task/Core.hs
+++ b/Omni/Task/Core.hs
@@ -45,10 +45,10 @@ data Task = Task
}
deriving (Show, Eq, Generic)
-data TaskType = Epic | WorkTask | HumanTask
+data TaskType = Epic | WorkTask
deriving (Show, Eq, Read, Generic)
-data Status = Draft | Open | InProgress | Review | Approved | Done
+data Status = Draft | Open | InProgress | Review | Approved | Done | NeedsHelp
deriving (Show, Eq, Read, Generic)
-- Priority levels (matching beads convention)
@@ -86,7 +86,7 @@ data EpicForReview = EpicForReview
data HumanActionItems = HumanActionItems
{ failedTasks :: [Task],
epicsInReview :: [EpicForReview],
- humanTasks :: [Task]
+ tasksNeedingHelp :: [Task]
}
deriving (Show, Eq, Generic)
@@ -806,8 +806,8 @@ getReadyTasks = do
/= Epic
&& not (isParent (taskId task))
&& all (`elem` doneIds) (blockingDepIds task)
- && taskType task
- /= HumanTask
+ && taskStatus task
+ /= NeedsHelp
&& taskId task
`notElem` needsInterventionIds
pure <| filter isReady openTasks
@@ -920,6 +920,7 @@ showTaskTree maybeId = do
Review -> "[?]"
Approved -> "[+]"
Done -> "[✓]"
+ NeedsHelp -> "[!]"
coloredStatusStr = case taskType task of
Epic -> magenta statusStr
@@ -930,6 +931,7 @@ showTaskTree maybeId = do
Review -> magenta statusStr
Approved -> green statusStr
Done -> green statusStr
+ NeedsHelp -> yellow statusStr
nsStr = case taskNamespace task of
Nothing -> ""
@@ -988,6 +990,7 @@ printTask t = do
Review -> magenta s
Approved -> green s
Done -> green s
+ NeedsHelp -> yellow s
coloredTitle = if taskType t == Epic then bold (taskTitle t) else taskTitle t
coloredProgress = if taskType t == Epic then magenta progressInfo else progressInfo
@@ -1556,12 +1559,12 @@ getHumanActionItems = do
let completed = length [c | c <- children, taskStatus c == Done],
completed == total
]
- human = [t | t <- allTasks, taskType t == HumanTask, taskStatus t == Open]
+ needingHelp = [t | t <- allTasks, taskStatus t == NeedsHelp]
pure
HumanActionItems
{ failedTasks = failed,
epicsInReview = epicsReady,
- humanTasks = human
+ tasksNeedingHelp = needingHelp
}
-- | Get all retry contexts from the database