summaryrefslogtreecommitdiff
path: root/Omni/Task.hs
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-11-20 14:09:57 -0500
committerBen Sima <ben@bsima.me>2025-11-20 14:09:57 -0500
commiteab575ad7ce423f053c87c45225853dd51aa252f (patch)
tree55cc492c568ac27e3d2c7bdf869fa3e33cadc991 /Omni/Task.hs
parenta5faf8c31f619142e6f43d688f52d87c4edff341 (diff)
task: implement stats command
- Add 'task stats' command to show task statistics - Display total tasks, status breakdown (open/in-progress/done) - Show epic count, ready vs blocked tasks - Show task counts by priority (P0-P4) and namespace - Support both human-readable and JSON output (--json flag) - Add tests for stats command and stats --json - TaskStats data type with ToJSON/FromJSON instances All 31 tests passing. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Omni/Task.hs')
-rw-r--r--Omni/Task.hs20
1 files changed, 20 insertions, 0 deletions
diff --git a/Omni/Task.hs b/Omni/Task.hs
index 6d2da71..bbb78bb 100644
--- a/Omni/Task.hs
+++ b/Omni/Task.hs
@@ -45,6 +45,7 @@ Usage:
task update <id> <status> [--json]
task deps <id> [--json]
task tree [<id>] [--json]
+ task stats [--json]
task export [--flush]
task import -i <file>
task sync
@@ -60,6 +61,7 @@ Commands:
update Update task status
deps Show dependency tree
tree Show task tree (epics with children, or all epics if no ID given)
+ stats Show task statistics
export Export and consolidate tasks to JSONL
import Import tasks from JSONL file
sync Export and commit tasks to git (does NOT push)
@@ -227,6 +229,12 @@ move args
tree <- getTaskTree maybeId
outputJson tree
else showTaskTree maybeId
+ | args `Cli.has` Cli.command "stats" = do
+ if isJsonMode args
+ then do
+ stats <- getTaskStats
+ outputJson stats
+ else showTaskStats
| args `Cli.has` Cli.command "export" = do
exportTasks
putText "Exported and consolidated tasks to .tasks/tasks.jsonl"
@@ -454,6 +462,18 @@ cliTests =
case result of
Left err -> Test.assertFailure <| "Failed to parse 'sync': " <> show err
Right args -> args `Cli.has` Cli.command "sync" Test.@?= True,
+ Test.unit "stats command" <| do
+ let result = Docopt.parseArgs help ["stats"]
+ case result of
+ Left err -> Test.assertFailure <| "Failed to parse 'stats': " <> show err
+ Right args -> args `Cli.has` Cli.command "stats" Test.@?= True,
+ Test.unit "stats with --json flag" <| do
+ let result = Docopt.parseArgs help ["stats", "--json"]
+ case result of
+ Left err -> Test.assertFailure <| "Failed to parse 'stats --json': " <> show err
+ Right args -> do
+ args `Cli.has` Cli.command "stats" Test.@?= True
+ args `Cli.has` Cli.longOption "json" Test.@?= True,
Test.unit "create with flags in different order" <| do
let result = Docopt.parseArgs help ["create", "Test", "--json", "--priority=1", "--namespace=Omni/Task"]
case result of