From 45521bda259c54458404ca8cda18615f0d36b492 Mon Sep 17 00:00:00 2001 From: Omni Worker Date: Fri, 21 Nov 2025 18:07:21 -0500 Subject: feat: add description field to tasks Amp-Thread-ID: https://ampcode.com/threads/T-79499d9e-f4f4-40de-893c-524c32a45483 Co-authored-by: Amp --- Omni/Task/Core.hs | 47 +++++++++++++++++++++++++++++++++++------------ Omni/Task/RaceTest.hs | 4 ++-- 2 files changed, 37 insertions(+), 14 deletions(-) (limited to 'Omni/Task') diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs index 1441a54..24bb31c 100644 --- a/Omni/Task/Core.hs +++ b/Omni/Task/Core.hs @@ -33,6 +33,7 @@ data Task = Task taskStatus :: Status, taskPriority :: Priority, -- Priority level (0-4) taskDependencies :: [Dependency], -- List of dependencies with types + taskDescription :: Maybe Text, -- Optional detailed description taskCreatedAt :: UTCTime, taskUpdatedAt :: UTCTime } @@ -255,11 +256,11 @@ loadTasksInternal = do then Nothing else case decode (BLC.pack <| T.unpack line) of Just task -> Just task - Nothing -> migrateOldTask line + Nothing -> migrateTask line - -- Migrate old task format (with taskProject field or missing priority) to new format - migrateOldTask :: Text -> Maybe Task - migrateOldTask line = case Aeson.decode (BLC.pack <| T.unpack line) :: Maybe Aeson.Object of + -- Migrate old task formats to new format + migrateTask :: Text -> Maybe Task + migrateTask line = case Aeson.decode (BLC.pack <| T.unpack line) :: Maybe Aeson.Object of Nothing -> Nothing Just obj -> let taskId' = KM.lookup "taskId" obj +> parseMaybe Aeson.parseJSON @@ -267,12 +268,22 @@ loadTasksInternal = do taskStatus' = KM.lookup "taskStatus" obj +> parseMaybe Aeson.parseJSON taskCreatedAt' = KM.lookup "taskCreatedAt" obj +> parseMaybe Aeson.parseJSON taskUpdatedAt' = KM.lookup "taskUpdatedAt" obj +> parseMaybe Aeson.parseJSON - -- Extract old taskDependencies (could be [Text] or [Dependency]) - oldDeps = KM.lookup "taskDependencies" obj +> parseMaybe Aeson.parseJSON :: Maybe [Text] - newDeps = maybe [] (map (\tid -> Dependency {depId = tid, depType = Blocks})) oldDeps + + -- Extract taskDescription (new field) + taskDescription' = KM.lookup "taskDescription" obj +> parseMaybe Aeson.parseJSON + + -- Extract dependencies (handle V1 [Dependency] and V0 [Text]) + v1Deps = KM.lookup "taskDependencies" obj +> parseMaybe Aeson.parseJSON :: Maybe [Dependency] + v0Deps = KM.lookup "taskDependencies" obj +> parseMaybe Aeson.parseJSON :: Maybe [Text] + finalDeps = case v1Deps of + Just ds -> ds + Nothing -> case v0Deps of + Just ts -> map (\tid -> Dependency {depId = tid, depType = Blocks}) ts + Nothing -> [] + -- taskProject is ignored in new format (use epics instead) - taskType' = WorkTask -- Old tasks become WorkTask by default - taskParent' = Nothing + taskType' = fromMaybe WorkTask (KM.lookup "taskType" obj +> parseMaybe Aeson.parseJSON) + taskParent' = KM.lookup "taskParent" obj +> parseMaybe Aeson.parseJSON taskNamespace' = KM.lookup "taskNamespace" obj +> parseMaybe Aeson.parseJSON -- Default priority to P2 (medium) for old tasks taskPriority' = fromMaybe P2 (KM.lookup "taskPriority" obj +> parseMaybe Aeson.parseJSON) @@ -287,7 +298,8 @@ loadTasksInternal = do taskNamespace = taskNamespace', taskStatus = status, taskPriority = taskPriority', - taskDependencies = newDeps, + taskDependencies = finalDeps, + taskDescription = taskDescription', taskCreatedAt = created, taskUpdatedAt = updated } @@ -304,8 +316,8 @@ saveTaskInternal task = do BLC.appendFile tasksFile (json <> "\n") -- Create a new task -createTask :: Text -> TaskType -> Maybe Text -> Maybe Text -> Priority -> [Dependency] -> IO Task -createTask title taskType parent namespace priority deps = +createTask :: Text -> TaskType -> Maybe Text -> Maybe Text -> Priority -> [Dependency] -> Maybe Text -> IO Task +createTask title taskType parent namespace priority deps description = withTaskWriteLock <| do tid <- case parent of Nothing -> generateId @@ -323,6 +335,7 @@ createTask title taskType parent namespace priority deps = taskStatus = Open, taskPriority = priority, taskDependencies = deps, + taskDescription = description, taskCreatedAt = now, taskUpdatedAt = now } @@ -632,6 +645,16 @@ showTaskDetailed t = do putText "" putText "Dependencies:" traverse_ printDependency (taskDependencies t) + + -- Show description + case taskDescription t of + Nothing -> pure () + Just desc -> do + putText "" + putText "Description:" + -- Indent description for better readability + let indented = T.unlines <| map (" " <>) (T.lines desc) + putText indented putText "" where diff --git a/Omni/Task/RaceTest.hs b/Omni/Task/RaceTest.hs index 10d3451..cfadaca 100644 --- a/Omni/Task/RaceTest.hs +++ b/Omni/Task/RaceTest.hs @@ -29,7 +29,7 @@ raceTest = initTaskDb -- Create a parent epic - parent <- createTask "Parent Epic" Epic Nothing Nothing P2 [] + parent <- createTask "Parent Epic" Epic Nothing Nothing P2 [] Nothing let parentId = taskId parent -- Create multiple children concurrently @@ -40,7 +40,7 @@ raceTest = -- Run concurrent creations children <- mapConcurrently - (\i -> createTask ("Child " <> tshow i) WorkTask (Just parentId) Nothing P2 []) + (\i -> createTask ("Child " <> tshow i) WorkTask (Just parentId) Nothing P2 [] Nothing) indices -- Check for duplicates in generated IDs -- cgit v1.2.3