refactor(kanban): drop the turn author from the worker spawn env

No turn reads it: the spawned worker client only submits kanban.run, and an
owner gateway it starts strips HERMES_TURN_AUTHOR from its environment. The
owner sets the author itself (previous commit). This restores the
TERMINAL_CWD comment sentence about file_tools rejecting relative values.
The chat -q forwarding stays: it gives -q the same author contract as -Q.
This commit is contained in:
kshitijk4poor authored and kshitij committed 2026-10-26 13:04:58 +05:30
1 parent 08f954e505
commit 95953ea5b7
2 files changed
+8 -46

No files matched your search

+4 -4
View File
@@ -2814,10 +2814,10 @@ def _default_spawn(task: Task, workspace: str, *, board: Optional[str] = None) -
# Tag the session `kanban` so session-browsing surfaces filter it out by
# source instead of rendering one sidebar row per attempt.
env["HERMES_SESSION_SOURCE"] = "kanban"
# The worker's prompts are this dispatcher's, not the operator's: a bot author keeps memory
# providers from filing "work kanban task t_..." and the worker's reply under the human's peer.
from agent.turn_author import bot_author_id, turn_author_env
env.update(turn_author_env({"id": bot_author_id("kanban"), "name": "Kanban dispatcher", "is_bot": True}))
# TERMINAL_CWD takes precedence over process cwd in file_tools and
# build_context_files_prompt; without it relative writes land in the gateway
# user's home and workers load the gateway's AGENTS.md. file_tools rejects
# relative / sentinel values, so only set a real absolute directory.
# Pin TERMINAL_CWD to the task's workspace so the worker's file tools and context-file loader anchor on
# the workspace, not whatever cwd the dispatching gateway happened to export. The worker subprocess is
# already launched with cwd=workspace, but TERMINAL_CWD takes precedence over the process cwd in both
@@ -1,57 +1,19 @@
"""A Kanban worker's turns are authored by the dispatcher, not the operator.
"""A dispatcher-authored ``chat -q`` run carries its turn author, as ``chat -Q`` already does.
The dispatcher spawns ``hermes chat -q "work kanban task <id>"``. Without an author, memory providers
filed that prompt and the worker's reply under the human's peer ("the user mentioned kanban task
t_..."). The spawn now names a bot author and the non-quiet one-shot path forwards it to every turn,
the same contract the quiet path and Bot Mode deliveries already follow.
``HERMES_TURN_AUTHOR`` names who wrote a one-shot run's prompts. The non-quiet ``-q`` path ignored it,
so the turn reached memory providers as the operator's and tool subprocesses inherited the variable.
"""
from __future__ import annotations
import os
import subprocess
from types import SimpleNamespace
from unittest.mock import Mock
import pytest
import cli
from agent.turn_author import TURN_AUTHOR_ENV, parse_turn_author
def _task(kb):
return kb.Task(
id="t_author", title="author", body=None, assignee="elias", status="running", priority=0,
created_by="test", created_at=1, started_at=None, completed_at=None, workspace_kind="dir",
workspace_path=None, claim_lock="lock", claim_expires=None, tenant=None, current_run_id=3,
)
def test_worker_spawn_names_the_dispatcher_as_a_bot_author(monkeypatch, tmp_path):
root = tmp_path / ".hermes"
(root / "profiles" / "elias").mkdir(parents=True)
root.joinpath("config.yaml").write_text("{}\n", encoding="utf-8")
monkeypatch.setenv("HERMES_HOME", str(root))
monkeypatch.setenv(TURN_AUTHOR_ENV, '{"id": "operator", "name": "human", "is_bot": false}')
from hermes_cli import kanban_db as kb
from hermes_cli import kanban_db_dispatch as kbd
monkeypatch.setattr(kbd, "_resolve_hermes_argv", lambda: ["hermes"])
captured = {}
def fake_popen(cmd, *args, **kwargs):
captured["env"] = dict(kwargs.get("env") or {})
return SimpleNamespace(pid=4321)
monkeypatch.setattr(subprocess, "Popen", fake_popen)
workspace = tmp_path / "workspace"
workspace.mkdir()
kbd._default_spawn(_task(kb), str(workspace))
author = parse_turn_author(captured["env"].get(TURN_AUTHOR_ENV))
assert author is not None and author["is_bot"] is True
assert author["id"].startswith("bot:")
from agent.turn_author import TURN_AUTHOR_ENV
def _one_shot_cli(monkeypatch):