← Back to task

Commit 7c9a3425

commit 7c9a3425706574f27753c548295234632ac77165
Author: Coder Agent <coder@agents.omni>
Date:   Wed Feb 18 12:44:39 2026

    Auto-detect agent author via OMNI_AUTHOR env var
    
    In Omni/Pipeline/Dev.hs spawnDev, set OMNI_AUTHOR=agent:engineer in
    the spawned process environment so agents running inside the pipeline
    automatically get correct attribution.
    
    In Omni/Task.hs parseAuthor, check OMNI_AUTHOR env var as fallback
    when no --author flag is given. Explicit --author still takes
    precedence; if neither is set, defaults to Human.
    
    Task-Id: t-635

diff --git a/Omni/Pipeline/Dev.hs b/Omni/Pipeline/Dev.hs
index aa32615e..5e9371b7 100644
--- a/Omni/Pipeline/Dev.hs
+++ b/Omni/Pipeline/Dev.hs
@@ -16,6 +16,7 @@ import qualified Omni.Pipeline.Core as Core
 import qualified Omni.Pipeline.Git as Git
 import qualified Omni.Task.Core as Task
 import qualified System.Directory as Dir
+import qualified System.Environment as Env
 import qualified System.Exit as Exit
 import qualified System.IO as IO
 import qualified System.Process as Process
@@ -114,10 +115,15 @@ spawnDev cfg workspace task patchset maybeReviewFeedback dbRowId = do
   logHandle <- IO.openFile logFile IO.WriteMode
   IO.hSetBuffering logHandle IO.LineBuffering
 
+  -- Inherit current environment and add OMNI_AUTHOR for agent attribution
+  parentEnv <- Env.getEnvironment
+  let agentEnv = Just (("OMNI_AUTHOR", "agent:engineer") : parentEnv)
+
   -- Spawn pi directly with stdout/stderr to log file
   let cp =
         (Process.proc "pi" piArgs)
           { Process.cwd = Just workspace,
+            Process.env = agentEnv,
             Process.std_in = Process.NoStream,
             Process.std_out = Process.UseHandle logHandle,
             Process.std_err = Process.UseHandle logHandle,
diff --git a/Omni/Task.hs b/Omni/Task.hs
index c5b525b0..97225215 100644
--- a/Omni/Task.hs
+++ b/Omni/Task.hs
@@ -21,7 +21,7 @@ import qualified Omni.Task.MigrationTest as MigrationTest
 import qualified Omni.Task.RaceTest as RaceTest
 import qualified Omni.Test as Test
 import System.Directory (createDirectoryIfMissing, doesFileExist, removeFile)
-import System.Environment (setEnv)
+import System.Environment (lookupEnv, setEnv)
 import qualified Test.Tasty as Tasty
 import Web.HttpApiData (parseQueryParam)
 import Prelude (read)
@@ -344,15 +344,14 @@ doComment :: GlobalOpts -> String -> String -> Maybe String -> IO ()
 doComment GlobalOpts {..} tidStr message authorStr = do
   for_ globalDb (setEnv "TASK_DB_PATH")
   let tid = T.pack tidStr
-      author = parseAuthor authorStr
+  author <- parseAuthor authorStr
   updatedTask <- addComment tid (T.pack message) author
   if globalJson
     then outputJson updatedTask
     else putStrLn <| "Added comment to task: " <> T.unpack tid
 
-parseAuthor :: Maybe String -> CommentAuthor
-parseAuthor Nothing = Human
-parseAuthor (Just s) = case map Char.toLower s of
+parseAuthor :: Maybe String -> IO CommentAuthor
+parseAuthor (Just s) = pure <| case map Char.toLower s of
   "human" -> Human
   "system" -> System
   "agent:engineer" -> Agent Engineer
@@ -361,6 +360,19 @@ parseAuthor (Just s) = case map Char.toLower s of
   "agent:productmgr" -> Agent ProductMgr
   "agent" -> Agent Engineer
   _ -> Human
+parseAuthor Nothing = do
+  envAuthor <- lookupEnv "OMNI_AUTHOR"
+  case envAuthor of
+    Nothing -> pure Human
+    Just s -> pure <| case map Char.toLower s of
+      "human" -> Human
+      "system" -> System
+      "agent:engineer" -> Agent Engineer
+      "agent:reviewer" -> Agent Reviewer
+      "agent:designer" -> Agent Designer
+      "agent:productmgr" -> Agent ProductMgr
+      "agent" -> Agent Engineer
+      _ -> Human
 
 -- | list command
 listParser :: Cli.Parser (IO ())