Skip to content

fix(cli): forward --worktree to run_oneshot so -z -w works (#67458) - #67484

Open
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/67458-worktree-oneshot
Open

fix(cli): forward --worktree to run_oneshot so -z -w works (#67458)#67484
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/67458-worktree-oneshot

Conversation

@webtecnica

Copy link
Copy Markdown
Contributor

Closes #67458.

Problem

The --worktree / -w flag was silently ignored in one-shot mode (-z). Running hermes -z "make a commit" -w would commit directly to the current branch instead of using an isolated git worktree.

Root cause

run_oneshot() in hermes_cli/oneshot.py didn't accept a worktree parameter, and neither call site in hermes_cli/main.py forwarded the parsed worktree flag.

Fix

  • Added worktree: bool = False parameter to run_oneshot()
  • Wired worktree setup (imports from cli.py: _git_repo_root, _prune_stale_worktrees, _setup_worktree) and cleanup (_cleanup_worktree) — mirroring the interactive-mode path
  • Set HERMES_CWD and TERMINAL_CWD env vars so the agent runs inside the worktree
  • Clean up the worktree in the finally block (preserving it when it has unpushed commits — same policy as interactive mode)
  • Forward worktree=getattr(args, "worktree", False) from both run_oneshot() call sites in main.py

Testing

  • Verified the fix compiles and the diff is minimal (only 42 lines added across 2 files)
  • The worktree functions reused from cli.py are already covered by tests/cli/test_worktree.py

…rch#67458)

The --worktree/-w flag was silently ignored in one-shot mode (-z):
run_oneshot() didn't accept a worktree parameter, and neither call
site in main.py forwarded the parsed flag.  Commits landed on the
current branch instead of an isolated worktree.

- Add  to run_oneshot() in hermes_cli/oneshot.py
- Wire worktree setup (git_repo_root, prune_stale_worktrees,
  _setup_worktree) and cleanup in oneshot.py, mirroring the
  interactive-mode path in cli.py
- Set HERMES_CWD and TERMINAL_CWD so the agent runs inside the
  worktree directory
- Clean up the worktree in the finally block (preserving it when
  it has unpushed commits, same policy as interactive mode)
- Pass worktree=getattr(args, 'worktree', False) from both
  run_oneshot() call sites in main.py
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard needs-decision Awaiting maintainer decision before any implementation labels Jul 19, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #67471 and #67476 for #67458. This is a competing isolated-worktree implementation with different CWD/cleanup handling; #67471 rejects the unsupported combination and #67476 supplies a separately tested implementation. Maintainer choice requested.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for covering both one-shot dispatch paths; the current-main omission is real (hermes_cli/main.py:12970-12976 and 15127-15133).

Problems

  • hermes_cli/oneshot.py:251 invokes _setup_worktree() before stdout redirection, but that helper prints creation details (cli.py:1630-1632). The added cleanup at line 303 also prints to stdout (cli.py:1776-1777, 1811). This breaks the documented -z contract that stdout is the final response only (hermes_cli/main.py:15121-15122).
  • Lines 257-258 replace HERMES_CWD and TERMINAL_CWD, but the finally block does not restore them. After cleanup removes the worktree, an in-process caller can retain a dangling TERMINAL_CWD, which agent/runtime_cwd.py:67-73 consumes.

Suggested changes

  • Redirect setup and cleanup notices to stderr and restore both environment variables in the final cleanup path.
  • Add forwarding and lifecycle regressions for both dispatches, stdout purity, setup failure, and environment restoration.

Automated hermes-sweeper review.

Comment thread hermes_cli/oneshot.py
repo = _git_repo_root()
if repo:
_prune_stale_worktrees(repo)
_wt_info = _setup_worktree()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

_setup_worktree() prints creation messages to stdout (cli.py:1630-1632), but -z promises stdout contains only the final response. Route this helper's output to stderr before calling it.

Comment thread hermes_cli/oneshot.py
)
return 1
os.environ["HERMES_CWD"] = _wt_info["path"]
os.environ["TERMINAL_CWD"] = _wt_info["path"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Save the prior CWD environment values and restore them in the final cleanup path. As written, a direct caller retains TERMINAL_CWD after _cleanup_worktree() may delete this path.

Comment thread hermes_cli/oneshot.py
if _wt_info is not None:
try:
from cli import _cleanup_worktree
_cleanup_worktree(_wt_info)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

_cleanup_worktree() prints both normal cleanup and unpushed-commit notices to stdout (cli.py:1776-1777, 1811). Redirect this call to real_stderr so it cannot contaminate one-shot output.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 19, 2026
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Three PRs address #67458 by forwarding -w/--worktree through both one-shot dispatch paths and adding worktree setup and cleanup. #67471 changes the process cwd, #67476 retargets and restores TERMINAL_CWD while preserving stdout purity, and #67484 leaves the reviewed stdout and environment-restoration defects in its visible diff.

Related pull requests

Duplicates

#67471 and #67476 substantially implement the same honor--w solution; #67484 overlaps that solution but retains the documented stdout and environment-restoration defects.

Suggested consolidation

Keep #67476 open with a salvage path preserving its two dispatch forwards, fail-closed setup, clean stdout, TERMINAL_CWD restoration, cleanup, and targeted regressions. Close #67471 as a duplicate of #67476 despite its keep_open review because its revised diff now implements the same product choice with less explicit runtime-cwd handling; close #67484 as a duplicate of #67476 despite its keep_open review because its visible diff retains that review's stdout and dangling-environment issues.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I67458(["issue #67458 (open)"])
    subgraph Dup67471 ["PRs duplicating each other"]
        P67471["PR #67471 (open)"]
        P67476["PR #67476 (open)"]
        P67484["PR #67484 (open)"]
    end
    P67484 -.->|partial| I67458
    class I67458 open
    class P67471 open
    class P67476 open
    class P67484 open
    class P67476 best
    class P67484 target
    click I67458 "https://github.com/NousResearch/hermes-agent/issues/67458"
    click P67471 "https://github.com/NousResearch/hermes-agent/pull/67471"
    click P67476 "https://github.com/NousResearch/hermes-agent/pull/67476"
    click P67484 "https://github.com/NousResearch/hermes-agent/pull/67484"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 3 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 72 kB of PR diffs, 11 kB of issue/PR text, 10 kB of discussion (14 comments), 5 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

-w/--worktree is silently ignored in one-shot mode (-z): commits land on the current branch

4 participants