diff options
| author | Ben Sima <ben@bsima.me> | 2025-11-09 07:37:25 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bsima.me> | 2025-11-09 07:37:25 -0500 |
| commit | 04986e2fc5c8863672c2a84e644777505878318b (patch) | |
| tree | f95b6ad65d076ca6b420c571f52bf7e3f6469998 /Omni/Task | |
| parent | 1d98b463ac79905b542d45d632e5135ea90af585 (diff) | |
Add enhanced dependency types to task manager
Implement four dependency types based on beads patterns: - Blocks:
Hard dependency, blocks ready work queue (default) - DiscoveredFrom:
Work discovered during implementation (doesn't block) - ParentChild:
Epic/task relationships (blocks ready work) - Related: Soft
relationships (doesn't block)
Key changes: - New Dependency data type with depId and depType fields
- New DependencyType enum with four relationship types - Updated CLI
with --dep-type and --discovered-from flags - Enhanced getReadyTasks
to respect only blocking dependency types - Added comprehensive tests
for all dependency behaviors - Updated AGENTS.md with usage examples
and patterns
The discovered-from pattern is especially important for AI agents to
maintain context of work found during implementation while keeping
it immediately available in the ready work queue.
Amp-Thread-ID:
https://ampcode.com/threads/T-178b273a-3ac7-416c-a964-db89bac3c8f7
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Omni/Task')
| -rw-r--r-- | Omni/Task/Core.hs | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs index 6d9856f..1137d8d 100644 --- a/Omni/Task/Core.hs +++ b/Omni/Task/Core.hs @@ -21,7 +21,7 @@ data Task = Task taskParent :: Maybe Text, -- Parent epic ID taskNamespace :: Maybe Text, -- Optional namespace (e.g., "Omni/Task", "Biz/Cloud") taskStatus :: Status, - taskDependencies :: [Text], -- List of task IDs this depends on + taskDependencies :: [Dependency], -- List of dependencies with types taskCreatedAt :: UTCTime, taskUpdatedAt :: UTCTime } @@ -33,6 +33,19 @@ data TaskType = Epic | WorkTask data Status = Open | InProgress | Done deriving (Show, Eq, Generic) +data Dependency = Dependency + { depId :: Text, -- ID of the task this depends on + depType :: DependencyType -- Type of dependency relationship + } + deriving (Show, Eq, Generic) + +data DependencyType + = Blocks -- Hard dependency, blocks ready work queue + | DiscoveredFrom -- Work discovered during other work + | ParentChild -- Epic/subtask relationship + | Related -- Soft relationship, doesn't block + deriving (Show, Eq, Generic) + instance ToJSON TaskType instance FromJSON TaskType @@ -41,6 +54,14 @@ instance ToJSON Status instance FromJSON Status +instance ToJSON DependencyType + +instance FromJSON DependencyType + +instance ToJSON Dependency + +instance FromJSON Dependency + instance ToJSON Task instance FromJSON Task @@ -104,7 +125,7 @@ saveTask task = do BLC.appendFile ".tasks/tasks.jsonl" (json <> "\n") -- Create a new task -createTask :: Text -> TaskType -> Maybe Text -> Maybe Text -> [Text] -> IO Task +createTask :: Text -> TaskType -> Maybe Text -> Maybe Text -> [Dependency] -> IO Task createTask title taskType parent namespace deps = do tid <- generateId now <- getCurrentTime @@ -158,7 +179,9 @@ getReadyTasks = do allTasks <- loadTasks let openTasks = filter (\t -> taskStatus t /= Done) allTasks doneIds = map taskId <| filter (\t -> taskStatus t == Done) allTasks - isReady task = all (`elem` doneIds) (taskDependencies task) + -- Only Blocks and ParentChild dependencies block ready work + blockingDepIds task = [depId dep | dep <- taskDependencies task, depType dep `elem` [Blocks, ParentChild]] + isReady task = all (`elem` doneIds) (blockingDepIds task) pure <| filter isReady openTasks -- Show dependency tree for a task @@ -172,7 +195,8 @@ showDependencyTree tid = do printTree :: [Task] -> Task -> Int -> IO () printTree allTasks task indent = do putText <| T.pack (replicate (indent * 2) ' ') <> taskId task <> ": " <> taskTitle task - let deps = filter (\t -> taskId t `elem` taskDependencies task) allTasks + let depIds = map depId (taskDependencies task) + deps = filter (\t -> taskId t `elem` depIds) allTasks traverse_ (\dep -> printTree allTasks dep (indent + 1)) deps -- Helper to print a task |
