Skip to content

fix: throwaway repros silently used the live session - #2600

Open
HackAttack wants to merge 1 commit into
herdrdev:masterfrom
HackAttack:isolation-fail
Open

fix: throwaway repros silently used the live session#2600
HackAttack wants to merge 1 commit into
herdrdev:masterfrom
HackAttack:isolation-fail

Conversation

@HackAttack

@HackAttack HackAttack commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

The herdr-throwaway-repro skill did not have its intended effect. A disposable session never started, and once it failed there was nothing left to stop the reproduction from running in the user's live session.

The skill's only documented way to create a disposable session was herdr --session <name> typed into an outer pane. That launches the TUI, and a TUI launched from a Herdr-managed pane exits 1 with "nested herdr is disabled by default" unless the user opted into experimental.allow_nested.

The rejection was printed inside the scratch pane, which was closed later, while the driving shell only saw 25 seconds of "No such file or directory" from polling for a session socket that was never going to appear. Then it fell back to herdr pane send-text/send-keys/read with no explicit session and no env prefix, which hit the default session.

Fix by starting the disposable session with herdr --session <name> server, which is dispatched before the nested gate and needs no config change or outer pane. Address it with the --session flag, which marks the session explicit so the inherited HERDR_SOCKET_PATH is ignored and a missing session fails with server_not_running. The HERDR_SESSION variable the skill used for targeting does not do this; it loses to that inherited socket path and answers from the user's session instead.

@kangal-bot kangal-bot added the ai-review Trigger automated AI reviews for pull requests admitted by the PR gate label Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The throwaway reproduction workflow now starts an isolated headless server session, creates its initial workspace, targets commands explicitly, supports optional attached clients, and verifies cleanup. Related Herdr guidance and the changelog describe the isolation behavior.

Changes

Throwaway session isolation

Layer / File(s) Summary
Headless session startup
.agents/skills/herdr-throwaway-repro/SKILL.md
The workflow validates the session name, starts a uniquely named headless server, clears inherited session context, waits for the session, creates its first workspace, and supports an optional attached client.
Explicit control and cleanup
.agents/skills/herdr-throwaway-repro/SKILL.md
Commands select the disposable session with --session. pane run uses a direct pane ID and command. Cleanup verifies session removal and removes temporary resources.
Isolated-server guidance
skills/herdr/SKILL.md, docs/next/CHANGELOG.md
The guidance documents the explicit server subcommand, and the changelog records throwaway repository isolation.

Estimated code review effort: 1 (Trivial) | ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: preventing throwaway reproductions from using the live session.
Description check ✅ Passed The description directly explains the isolation failure, its cause, and the implemented fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8731fef1-46d1-4e5a-a8fe-e1a3dc923c35

📥 Commits

Reviewing files that changed from the base of the PR and between 6c6ddcd and 87141db.

📒 Files selected for processing (3)
  • .agents/skills/herdr-throwaway-repro/SKILL.md
  • docs/next/CHANGELOG.md
  • skills/herdr/SKILL.md

Comment thread .agents/skills/herdr-throwaway-repro/SKILL.md Outdated
Comment thread docs/next/CHANGELOG.md Outdated
@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown

Greptile Summary

The PR revises the throwaway-reproduction skill to explicitly target an isolated named headless server and documents session-selection safeguards.

  • Replaces the nested TUI startup with named headless-server guidance.
  • Requires explicit --session targeting for disposable-session control commands.
  • Adds workspace, optional nested-client, readiness, and cleanup instructions.
  • Updates the bundled skill safety guidance and changelog.

Confidence Score: 4/5

The PR is not yet safe to merge because the documented startup command still blocks the driving shell and prevents the reproduction workflow from continuing.

The attempted fix correctly selects headless server mode, but that mode runs synchronously and the skill supplies no concrete background invocation, leaving the previously reported workflow failure outstanding.

Files Needing Attention: .agents/skills/herdr-throwaway-repro/SKILL.md

Important Files Changed

Filename Overview
.agents/skills/herdr-throwaway-repro/SKILL.md Reworks disposable-session isolation comprehensively, but the attempted foreground-server fix still lacks a concrete nonblocking launch command.
skills/herdr/SKILL.md Updates general safety guidance to distinguish the headless server command from the nested TUI form.
docs/next/CHANGELOG.md Records the throwaway-reproduction isolation correction.

Sequence Diagram

sequenceDiagram
  participant Agent
  participant Shell
  participant Herdr as Headless server
  Agent->>Shell: herdr --session name server
  Shell->>Herdr: run_server()
  Herdr-->>Shell: blocks until shutdown
  Note over Agent,Shell: Readiness and workspace steps cannot execute
  Agent-xShell: session list / workspace create
Loading

Reviews (3): Last reviewed commit: "fix: throwaway repros silently used the ..." | Re-trigger Greptile

Comment thread .agents/skills/herdr-throwaway-repro/SKILL.md

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.agents/skills/herdr-throwaway-repro/SKILL.md (1)

50-60: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Run the server in the background before continuing.

The command ends with herdr --session <session-name> server, but the server stays in the foreground. A shell or pane that follows these instructions blocks at this step, so session list, workspace creation, and reproduction commands do not run.

Use the installed tool's background primitive, or background the process and redirect its output to a /var/tmp log.

Proposed shell change
-  herdr --session <session-name> server
+  nohup herdr --session <session-name> server \
+    >"/var/tmp/<session-name>-server.log" 2>&1 </dev/null &

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7daea657-a646-483a-bf63-c445b1a2ea86

📥 Commits

Reviewing files that changed from the base of the PR and between 87141db and 8e86978.

📒 Files selected for processing (2)
  • .agents/skills/herdr-throwaway-repro/SKILL.md
  • docs/next/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/next/CHANGELOG.md

Comment thread .agents/skills/herdr-throwaway-repro/SKILL.md Outdated
Comment thread .agents/skills/herdr-throwaway-repro/SKILL.md Outdated
The herdr-throwaway-repro skill did not have its intended effect. A
disposable session never started, and once it failed there was nothing
left to stop the reproduction from running in the user's live session.

The skill's only documented way to create a disposable session was
`herdr --session <name>` typed into an outer pane. That launches the
TUI, and a TUI launched from a Herdr-managed pane exits 1 with "nested
herdr is disabled by default" unless the user opted into
`experimental.allow_nested`.

The rejection was printed inside the scratch pane, which was closed
later, while the driving shell only saw 25 seconds of "No such file or
directory" from polling for a session socket that was never going to
appear. Then it fell back to `herder pane send-text/send-keys/read` with
no explicit session and no env prefix, which hit the default session.

Fix by starting the disposable session with `herdr --session <name>
server`, which is dispatched before the nested gate and needs no config
change or outer pane. Address it with the `--session` flag, which marks
the session explicit so the inherited HERDR_SOCKET_PATH is ignored and a
missing session fails with server_not_running. The HERDR_SESSION
variable the skill used for targeting does not do this; it loses to that
inherited socket path and answers from the user's session instead.
Comment on lines 58 to 68
```bash
# To be run as a background job
env \
-u HERDR_SOCKET_PATH \
-u HERDR_CLIENT_SOCKET_PATH \
-u HERDR_SESSION \
-u HERDR_WORKSPACE_ID \
-u HERDR_TAB_ID \
-u HERDR_PANE_ID \
herdr --session <session-name>
herdr --session <session-name> server
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Server launch still blocks

When an agent executes this startup block literally, herdr --session <session-name> server runs synchronously and occupies the shell until shutdown, so the readiness check, workspace creation, and remaining reproduction steps cannot execute. Referring to an unspecified harness background primitive does not provide an executable nonblocking launch.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f247886a-071d-4de4-80a9-a208fdafce70

📥 Commits

Reviewing files that changed from the base of the PR and between c7fc62a and 7708d15.

📒 Files selected for processing (2)
  • .agents/skills/herdr-throwaway-repro/SKILL.md
  • docs/next/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/next/CHANGELOG.md

Comment on lines 60 to +67
env \
-u HERDR_SOCKET_PATH \
-u HERDR_CLIENT_SOCKET_PATH \
-u HERDR_SESSION \
-u HERDR_WORKSPACE_ID \
-u HERDR_TAB_ID \
-u HERDR_PANE_ID \
herdr --session <session-name>
herdr --session <session-name> server

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate and quote the session name before shell interpolation.

The suggested repro-<topic>-<timestamp> format does not constrain <topic>. When the placeholder is replaced with whitespace, shell metacharacters, /, or .., the commands can split arguments, execute unintended commands, or escape /var/tmp. Require a name such as ^[A-Za-z0-9][A-Za-z0-9_-]*$, and quote every session-name expansion.

Proposed validation pattern
+case "$session_name" in
+  ''|*[!A-Za-z0-9_-]*) exit 1 ;;
+esac
+
-  herdr --session <session-name> server
+  herdr --session "$session_name" server

Comment on lines +80 to +82
```bash
printf '[experimental]\nallow_nested = true\n' > /var/tmp/<session-name>-config.toml
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Create the nested-client config with an exclusive temporary path.

printf ... > /var/tmp/<session-name>-config.toml can follow an existing symlink or overwrite an unrelated file. Cleanup can then remove that file. Use mktemp, store the returned path, pass that path through HERDR_CONFIG_PATH, and remove only that exact path.

Proposed temporary-file handling
-printf '[experimental]\nallow_nested = true\n' > /var/tmp/<session-name>-config.toml
+config_path="$(mktemp /var/tmp/herdr-repro-config.XXXXXX)"
+printf '[experimental]\nallow_nested = true\n' >"$config_path"

- HERDR_CONFIG_PATH=/var/tmp/<session-name>-config.toml
+ HERDR_CONFIG_PATH="$config_path"

- Remove /var/tmp/<session-name>-config.toml
+ Remove "$config_path"

Also applies to: 166-167

Comment on lines 90 to +102
## Address only the disposable session

Every control command issued from the parent must clear inherited socket overrides and explicitly select the temporary session:
Select the session with the `--session` flag on every control command:

```bash
env \
-u HERDR_SOCKET_PATH \
-u HERDR_CLIENT_SOCKET_PATH \
-u HERDR_WORKSPACE_ID \
-u HERDR_TAB_ID \
-u HERDR_PANE_ID \
HERDR_SESSION=<session-name> \
herdr pane list
herdr --session <session-name> pane list
```

Repeat this prefix for every command. Do not rely on shell state persisting between tool calls.
The flag marks the session explicit, so Herdr ignores the `HERDR_SOCKET_PATH` inherited from the surrounding pane. Naming a session that is not running then fails with `server_not_running` instead of answering from the user's session.

The `HERDR_SESSION` environment variable does not do this. Inside a Herdr pane `HERDR_SOCKET_PATH` already points at the user's server and takes precedence over that variable, so `HERDR_SESSION=<session-name> herdr pane list` reads and mutates the user's session and reports success. A bare `herdr pane list` does the same. Treat any command without `--session` as aimed at the user's session.

Repeat the flag on every server-scoped command. Do not rely on shell state persisting between tool calls.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- inherited target identifiers ---'
rg -n -C 8 \
  'HERDR_(WORKSPACE_ID|TAB_ID|PANE_ID)|--session' \
  src tests docs || true

printf '%s\n' '--- target resolution ---'
rg -n -C 10 \
  'resolve.*(workspace|tab|pane)|current.*(workspace|tab|pane)|default.*(workspace|tab|pane)' \
  src tests || true

Repository: herdrdev/herdr

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- relevant files ---'
git ls-files | rg '(^|/)(SKILL\.md|.*(cli|session|target|env).*)$' | head -200

printf '%s\n' '--- exact environment-variable references ---'
rg -n -S \
  'HERDR_(WORKSPACE_ID|TAB_ID|PANE_ID|SESSION|SOCKET_PATH)|session' \
  --glob '!src/ghostty/**' \
  --glob '!target/**' \
  --glob '!*.lock' \
  .agents src tests docs 2>/dev/null | head -1000

printf '%s\n' '--- skill context ---'
cat -n .agents/skills/herdr-throwaway-repro/SKILL.md | sed -n '70,115p'

Repository: herdrdev/herdr

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- session selection and CLI setup ---'
cat -n src/session.rs | sed -n '1,190p'
cat -n src/cli.rs | sed -n '1,180p'

printf '%s\n' '--- target parsing and CLI command handlers ---'
cat -n src/app/terminal_targets.rs | sed -n '1,260p'
cat -n src/cli/pane.rs | sed -n '1,240p'
cat -n src/cli/workspace.rs | sed -n '1,180p'
cat -n src/cli/tab.rs | sed -n '1,180p'

printf '%s\n' '--- target environment names in current source ---'
rg -n -S \
  'HERDR_(WORKSPACE_ID|TAB_ID|PANE_ID|ACTIVE_WORKSPACE_ID|ACTIVE_TAB_ID|ACTIVE_PANE_ID)' \
  src tests .agents \
  --glob '!src/ghostty/**' \
  --glob '!vendor/**' || true

Repository: herdrdev/herdr

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- all CLI uses of inherited caller IDs ---'
rg -n -C 6 \
  'HERDR_(WORKSPACE_ID|TAB_ID|PANE_ID)|parse_optional_current|--current|caller_pane_id' \
  src/cli/pane.rs src/cli/workspace.rs src/cli/tab.rs src/cli/runtime.rs src/cli.rs

printf '%s\n' '--- server-side current-target handling ---'
rg -n -C 10 \
  'PaneCurrent|caller_pane_id|workspace_id.*caller|current.*pane|public_pane_id|public_workspace_id|public_tab_id' \
  src/api src/app src/server \
  --glob '!**/ghostty/**' | head -1200

printf '%s\n' '--- ID generation and environment injection ---'
cat -n src/integration/env.rs | sed -n '1,180p'
cat -n src/pane.rs | sed -n '110,165p'
rg -n -C 8 \
  'fn (public_pane_id|public_workspace_id|public_tab_id)|public_pane_id\(' \
  src/app src | head -500

Repository: herdrdev/herdr

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- exact target parser implementations ---'
cat -n src/cli/pane.rs | sed -n '227,295p;544,590p;623,680p;900,990p'
cat -n src/cli/runtime.rs | sed -n '1,180p'

printf '%s\n' '--- workspace and public-ID construction ---'
rg -n -C 8 \
  'pub fn (public_(workspace|tab|pane)_id_for_number)|public_(workspace|tab|pane)_id_for_number|struct Workspace|fn test_new|WorkspaceId' \
  src/workspace.rs src/app/ids.rs src | head -800

printf '%s\n' '--- focused static behavioral verifier ---'
python3 - <<'PY'
from pathlib import Path

session = Path("src/session.rs").read_text()
pane = Path("src/cli/pane.rs").read_text()

assert 'apply_explicit_name(&session)?;' in session
assert 'std::env::remove_var("HERDR_PANE_ID")' not in session
assert 'std::env::remove_var("HERDR_WORKSPACE_ID")' not in session
assert 'std::env::remove_var("HERDR_TAB_ID")' not in session

assert 'std::env::var("HERDR_PANE_ID")' in pane
assert '--current' in pane
print("explicit --session selection does not clear inherited target IDs")
print("HERDR_PANE_ID remains an input to pane current-target parsing")
PY

Repository: herdrdev/herdr

Length of output: 50370


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workspace ID generation and cross-session uniqueness ---'
cat -n src/workspace.rs | sed -n '90,170p;1260,1315p'
rg -n -C 8 \
  'generate_workspace_id|NEXT_WORKSPACE|Atomic.*workspace|workspace.*id' \
  src/workspace.rs src | head -500

printf '%s\n' '--- API fallback for omitted and explicit pane targets ---'
rg -n -C 12 \
  'PaneLayout|PaneSplit|PaneInputSet|PaneCurrent|params\.pane_id|pane_id\.as|unwrap_or.*focused|focused.*pane' \
  src/api/server.rs src/server/headless.rs src/app | head -1200

printf '%s\n' '--- focused behavioral source verifier ---'
python3 - <<'PY'
from pathlib import Path

session = Path("src/session.rs").read_text()
pane = Path("src/cli/pane.rs").read_text()
ids = Path("src/workspace.rs").read_text()

checks = {
    "explicit session does not clear caller IDs": all(
        f'remove_var("HERDR_{name}")' not in session
        for name in ("WORKSPACE_ID", "TAB_ID", "PANE_ID")
    ),
    "pane current reads HERDR_PANE_ID": 'std::env::var("HERDR_PANE_ID")' in pane
        and 'caller_pane_id = env_pane_id.map' in pane,
    "pane split current reads HERDR_PANE_ID": 'ok_or("--current requires HERDR_PANE_ID")' in pane,
    "public pane IDs include workspace IDs": 'format!("{workspace_id}:p' in ids,
}
for label, result in checks.items():
    print(f"{label}: {result}")
assert all(checks.values())
PY

Repository: herdrdev/herdr

Length of output: 50371


Clear inherited caller IDs for disposable-session commands that use current targets.

--session selects the socket but does not clear HERDR_PANE_ID. Current-target selectors can resolve a parent-session ID to a different disposable-session pane. Run these commands with env -u HERDR_WORKSPACE_ID -u HERDR_TAB_ID -u HERDR_PANE_ID, or use explicit IDs returned by the disposable session.

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

Labels

ai-review Trigger automated AI reviews for pull requests admitted by the PR gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants