← Back to task

Commit 27792ace

commit 27792ace8ae994c84ccbed9b80671fd0e133bb6f
Author: Ben Sima <ben@bensima.com>
Date:   Thu Nov 27 09:53:20 2025

    Add task_activity table schema
    
    All components are in place: - `ActivityStage` enum with stages:
    Claiming, Running, Reviewing, Retryi - `TaskActivity` data type with
    all required fields - JSON instances (ToJSON/FromJSON) - SQLite
    instances (FromField/ToField for ActivityStage, FromRow/ToRow f -
    `task_activity` table in `initTaskDb`
    
    Build passes with no errors.
    
    Task-Id: t-148.1

diff --git a/Omni/Task/Core.hs b/Omni/Task/Core.hs
index d1d92d50..3a5dd492 100644
--- a/Omni/Task/Core.hs
+++ b/Omni/Task/Core.hs
@@ -82,6 +82,21 @@ data RetryContext = RetryContext
   }
   deriving (Show, Eq, Generic)
 
+-- Activity stage for task_activity tracking
+data ActivityStage = Claiming | Running | Reviewing | Retrying | Completed | Failed
+  deriving (Show, Eq, Read, Generic)
+
+-- Task activity log entry
+data TaskActivity = TaskActivity
+  { activityId :: Maybe Int, -- NULL for new entries, set by DB
+    activityTaskId :: Text,
+    activityTimestamp :: UTCTime,
+    activityStage :: ActivityStage,
+    activityMessage :: Maybe Text,
+    activityMetadata :: Maybe Text -- JSON for extra data
+  }
+  deriving (Show, Eq, Generic)
+
 instance ToJSON TaskType
 
 instance FromJSON TaskType
@@ -114,6 +129,14 @@ instance ToJSON RetryContext
 
 instance FromJSON RetryContext
 
+instance ToJSON ActivityStage
+
+instance FromJSON ActivityStage
+
+instance ToJSON TaskActivity
+
+instance FromJSON TaskActivity
+
 -- HTTP API Instances (for Servant query params)
 
 instance FromHttpApiData Status where
@@ -162,6 +185,16 @@ instance SQL.FromField Priority where
 instance SQL.ToField Priority where
   toField x = SQL.toField (show x :: String)
 
+instance SQL.FromField ActivityStage where
+  fromField f = do
+    t <- SQL.fromField f :: SQLOk.Ok String
+    case readMaybe t of
+      Just x -> pure x
+      Nothing -> SQL.returnError SQL.ConversionFailed f "Invalid ActivityStage"
+
+instance SQL.ToField ActivityStage where
+  toField x = SQL.toField (show x :: String)
+
 -- Store dependencies as JSON text
 instance SQL.FromField [Dependency] where
   fromField f = do
@@ -203,6 +236,26 @@ instance SQL.ToRow Task where
       SQL.toField (taskUpdatedAt t)
     ]
 
+instance SQL.FromRow TaskActivity where
+  fromRow =
+    TaskActivity
+      </ SQL.field
+      <*> SQL.field
+      <*> SQL.field
+      <*> SQL.field
+      <*> SQL.field
+      <*> SQL.field
+
+instance SQL.ToRow TaskActivity where
+  toRow a =
+    [ SQL.toField (activityId a),
+      SQL.toField (activityTaskId a),
+      SQL.toField (activityTimestamp a),
+      SQL.toField (activityStage a),
+      SQL.toField (activityMessage a),
+      SQL.toField (activityMetadata a)
+    ]
+
 -- | Case-insensitive ID comparison
 matchesId :: Text -> Text -> Bool
 matchesId id1 id2 = normalizeId id1 == normalizeId id2
@@ -294,6 +347,17 @@ initTaskDb = do
       \ attempt INTEGER NOT NULL DEFAULT 1, \
       \ reason TEXT NOT NULL \
       \)"
+    SQL.execute_
+      conn
+      "CREATE TABLE IF NOT EXISTS task_activity (\
+      \ id INTEGER PRIMARY KEY AUTOINCREMENT, \
+      \ task_id TEXT NOT NULL, \
+      \ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, \
+      \ stage TEXT NOT NULL, \
+      \ message TEXT, \
+      \ metadata TEXT, \
+      \ FOREIGN KEY (task_id) REFERENCES tasks(id) \
+      \)"
 
 -- Generate a sequential task ID (t-1, t-2, t-3, ...)
 generateId :: IO Text