summaryrefslogtreecommitdiff
path: root/Omni/Task
diff options
context:
space:
mode:
Diffstat (limited to 'Omni/Task')
-rw-r--r--Omni/Task/Core.hs26
1 files changed, 26 insertions, 0 deletions
diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs
index d64d607..e4986c1 100644
--- a/Omni/Task/Core.hs
+++ b/Omni/Task/Core.hs
@@ -11,6 +11,7 @@ import Data.Aeson (FromJSON, ToJSON, decode, encode)
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy.Char8 as BLC
import qualified Data.List as List
+import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Data.Time (UTCTime, diffUTCTime, getCurrentTime)
@@ -1395,6 +1396,31 @@ getBlockedTasks = do
`notElem` doneIds
pure [t | t <- allTasks, isBlocked t]
+-- | Count how many tasks are transitively blocked by this task
+getBlockingImpact :: [Task] -> Task -> Int
+getBlockingImpact allTasks task =
+ length (getTransitiveDependents allTasks (taskId task))
+
+-- | Get all tasks that depend on this task (directly or transitively)
+-- Uses a Set to track visited nodes and avoid infinite loops from circular deps
+getTransitiveDependents :: [Task] -> Text -> [Task]
+getTransitiveDependents allTasks tid = go Set.empty [tid]
+ where
+ go :: Set.Set Text -> [Text] -> [Task]
+ go _ [] = []
+ go visited (current : rest)
+ | Set.member current visited = go visited rest
+ | otherwise =
+ let directDeps = [t | t <- allTasks, dependsOnTask current t]
+ newIds = [taskId t | t <- directDeps, not (Set.member (taskId t) visited)]
+ visited' = Set.insert current visited
+ in directDeps ++ go visited' (newIds ++ rest)
+
+-- | Check if task depends on given ID with Blocks dependency type
+dependsOnTask :: Text -> Task -> Bool
+dependsOnTask tid task =
+ any (\d -> matchesId (depId d) tid && depType d == Blocks) (taskDependencies task)
+
-- | Get tasks that have failed 3+ times and need human intervention
getInterventionTasks :: IO [Task]
getInterventionTasks = do