fix(kanban): persist worker session metadata on completion

Salvages #25579 by @wesleysimplicio. Stamps task_runs.metadata.worker_session_id
from HERMES_SESSION_ID on kanban_complete. Cherry-picked the substantive
commit (not the AUTHOR_MAP fixup tip) onto current main.
This commit is contained in:
wesleysimplicio 2026-05-18 20:22:22 -07:00 committed by Teknium
parent 4f6101cc74
commit 86279160b0
2 changed files with 68 additions and 0 deletions

View file

@ -128,6 +128,7 @@ def worker_env(monkeypatch, tmp_path):
home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(home))
monkeypatch.setenv("HERMES_PROFILE", "test-worker")
monkeypatch.delenv("HERMES_SESSION_ID", raising=False)
from pathlib import Path as _Path
monkeypatch.setattr(_Path, "home", lambda: tmp_path)
@ -310,6 +311,58 @@ def test_complete_metadata_round_trips_through_show(worker_env):
assert shown["runs"][-1]["metadata"] == handoff
def test_complete_stamps_worker_session_id_from_env(monkeypatch, worker_env):
from tools import kanban_tools as kt
monkeypatch.setenv("HERMES_SESSION_ID", "session-trusted")
metadata = {"files": 2, "worker_session_id": "user-spoof"}
out = kt._handle_complete({
"summary": "done by scoped worker",
"metadata": metadata,
})
assert json.loads(out)["ok"] is True
assert metadata["worker_session_id"] == "user-spoof"
from hermes_cli import kanban_db as kb
conn = kb.connect()
try:
run = kb.latest_run(conn, worker_env)
assert run.metadata == {
"files": 2,
"worker_session_id": "session-trusted",
}
finally:
conn.close()
def test_complete_does_not_stamp_worker_session_id_without_scoped_task(
monkeypatch, worker_env
):
from tools import kanban_tools as kt
monkeypatch.delenv("HERMES_KANBAN_TASK", raising=False)
monkeypatch.setenv("HERMES_SESSION_ID", "session-trusted")
out = kt._handle_complete({
"task_id": worker_env,
"summary": "done outside worker scope",
"metadata": {"files": 2, "worker_session_id": "user-provided"},
})
assert json.loads(out)["ok"] is True
from hermes_cli import kanban_db as kb
conn = kb.connect()
try:
run = kb.latest_run(conn, worker_env)
assert run.metadata == {
"files": 2,
"worker_session_id": "user-provided",
}
finally:
conn.close()
def test_complete_with_result_only(worker_env):
"""`result` alone (without summary) is accepted for legacy compat."""
from tools import kanban_tools as kt

View file

@ -112,6 +112,20 @@ def _worker_run_id(task_id: str) -> Optional[int]:
return None
def _stamp_worker_session_metadata(
task_id: str, metadata: Optional[dict]
) -> Optional[dict]:
"""Add trusted worker session id metadata for this worker's own task."""
if os.environ.get("HERMES_KANBAN_TASK") != task_id:
return metadata
session_id = os.environ.get("HERMES_SESSION_ID")
if not session_id:
return metadata
stamped = dict(metadata or {})
stamped["worker_session_id"] = session_id
return stamped
def _enforce_worker_task_ownership(tid: str) -> Optional[str]:
"""Reject worker-driven destructive calls on foreign task IDs.
@ -432,6 +446,7 @@ def _handle_complete(args: dict, **kw) -> str:
return tool_error(
f"metadata must be an object/dict, got {type(metadata).__name__}"
)
metadata = _stamp_worker_session_metadata(tid, metadata)
try:
kb, conn = _connect()
try: