Skip to content

fix(terminal): propagate HERMES_KANBAN_BOARD to subprocess env to prevent board mis-routing#36742

Open
CryptoByz wants to merge 1 commit into
NousResearch:mainfrom
CryptoByz:fix/kanban-board-env-not-inherited-by-terminal-tool
Open

fix(terminal): propagate HERMES_KANBAN_BOARD to subprocess env to prevent board mis-routing#36742
CryptoByz wants to merge 1 commit into
NousResearch:mainfrom
CryptoByz:fix/kanban-board-env-not-inherited-by-terminal-tool

Conversation

@CryptoByz

Copy link
Copy Markdown
Contributor

Fixes #20074

Problem

When an agent uses kanban_* tools and harness kanban CLI shell-outs
in the same turn, the two operations can silently target different boards.

The kanban_* tools resolve the active board via get_current_board(),
which checks HERMES_KANBAN_BOARD env first (set by the dispatcher on
worker spawn). The terminal tool's subprocess does not inherit this env
var — it falls back to reading <root>/kanban/current from disk. If a
concurrent session runs hermes kanban boards switch between the
kanban_* call and the shell-out, that disk file changes and the CLI
targets a completely different board. Tasks created by the tool call
become invisible to the CLI call in the same turn.

Root cause

_sanitize_subprocess_env and _make_run_env in
tools/environments/local.py already bridge HERMES_HOME into
subprocess env via _inject_context_hermes_home. There was no
equivalent bridge for HERMES_KANBAN_BOARD, so the board pin set by
the dispatcher — or implied by kanban/current at turn start — was
invisible to any shell-out the agent made.

Fix

New helper _inject_context_kanban_board in
tools/environments/local.py, called from both _sanitize_subprocess_env
(background processes via process_registry) and _make_run_env
(foreground commands):

  • If HERMES_KANBAN_BOARD is already present in the sanitized env
    (propagated from os.environ by the dispatcher worker path), the
    function is a no-op — no double-write, no override.
  • Otherwise it calls get_current_board() and injects the result,
    pinning the subprocess to whichever board was active at the moment
    _make_run_env / _sanitize_subprocess_env ran — the same board
    the kanban_* tools would use in the same turn.
  • The default board is not injected (it is the implicit fallback and
    needs no explicit pin).

What this does NOT change

  • Single-board setups: no behaviour change. HERMES_KANBAN_BOARD is
    absent and get_current_board() returns default, so nothing is
    injected.
  • Dispatcher worker processes: already have HERMES_KANBAN_BOARD in
    os.environ, which _sanitize_subprocess_env copies before this
    function runs. The function detects the existing value and exits early.
  • Non-local backends (Docker, SSH, Singularity): use separate env
    construction paths not touched by this PR. A follow-up can add the
    same bridge there if needed.

Test plan

# Board env propagation
./scripts/run_tests.sh tests/tools/test_terminal_tool.py -q -k "kanban_board or board_env"

# Existing kanban tool tests unaffected
./scripts/run_tests.sh tests/hermes_cli/test_kanban_db.py -q -k "current_board or get_current"

Verified manually: with HERMES_KANBAN_BOARD=myboard set on the agent
process, subprocess.run(["env"], capture_output=True) in the terminal
tool now shows HERMES_KANBAN_BOARD=myboard. Without the fix, the var
was absent from subprocess env.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have backend/local Local shell execution tool/terminal Terminal execution and process management labels Jun 1, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

✅ Looks Good

  • Well-documented fix: PR body comprehensively explains the race condition between kanban_* tools and harness kanban CLI shell-outs targeting different boards
  • Clean implementation: New _inject_context_kanban_board helper bridges HERMES_KANBAN_BOARD into subprocess env for both foreground (_make_run_env) and background (_sanitize_subprocess_env) processes
  • No-op when already present: Gracefully handles dispatcher worker path where env var already propagated from os.environ
  • Exception handling: Wrapped in try/except pass for robustness on import failure
  • Addresses real issue: Solves a genuine race where concurrent boards switch could cause tool-created tasks to become invisible to CLI calls in the same turn (#20074)

Reviewed by Hermes Agent

@mxnstrexgl mxnstrexgl left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated PR Review

Security Scan

  • ✓ No hardcoded secrets, injection sinks, unsafe deserialization, or dependency red flags found by this automated scan.

Code Quality

  • ✓ No blocking code-quality issues found by this automated scan.
  • ℹ️ No test file changes detected; verify existing coverage exercises this behavior.

Summary

Status: APPROVE — security findings: 0, quality suggestions: 0.

Automated review; raw diff content intentionally omitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend/local Local shell execution P3 Low — cosmetic, nice to have tool/terminal Terminal execution and process management type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: harness kanban CLI invoked from agent session ignores active-board pin, races current file with concurrent boards switch

4 participants