parallel-agents · herdr

四个 coding agent,一屏跑同一个 issue,拿到 diff 对比再挑一条合

一个真实 herdr 会话:4 个 pane、4 个 worktree、4 个不同角度的 coding agent,左侧 sidebar 实时打上 working / blocked / idle 图标;等每条分支落一个真实 commit,一份 DIFF_COMPARE.md 建议合哪条。

real herdr session · 4-agent 2×2
herdr TUI: left sidebar lists four claude agents at working / blocked / idle / idle states; the 2×2 grid on the right shows each pane's own screen.
working blocked idle unknown live-output detection · unknown once the agent exits
terminal recording · asciinema · 8s excerpt

Open herdr.cast in any asciinema player for the animated version, or view the GIF: herdr-session.gif.

herdr.cast 160×40 · v0.7.1 · monokai unedited
stats-aminimal patch
+19−2tests 2 / 2 green

bin/stats.js

Coerces every argv token through Number.isFinite, early-exits on empty, and switches stddev to divide by (n − 1). Smallest possible diff that closes the issue — but adds no tests, so the same regression could slip in next quarter.

stats-brewrite for clarity
+37−19tests 2 / 2 green

bin/stats.js

Splits parse / compute / print, replaces per-branch process.exit(1) with a single catch → console.error → exit at the top level, and exports the pieces for reuse. Reads well — but that's a wider structural change than a 30-line file is asking for today.

stats-ctest-first (TDD)
+39−2tests 5 / 5 green

bin/stats.jstest/stats.test.js

Wrote three new failing tests first (empty argv, non-numeric token, sample-stddev = 1.29099…), then the smallest change to greenify. Closes the issue AND leaves guardrails behind so the class of bug can't come back.

stats-droot-cause note
+39−6tests 2 / 2 green

ROOT_CAUSE.mdbin/stats.js

Wrote ROOT_CAUSE.md first — "two distinct bugs, one symptom" — then only the change the note justifies, plus a linkback comment at the top of bin/stats.js. Best explanation of *why*; the code change itself is close to stats-a.

Verdict — merge stats-c. It closes the issue and leaves behind a test suite that stops the same class of bug (empty input, non-numeric tokens, population-vs-sample σ) from returning. Carry stats-b's parse/compute split into a follow-up refactor once the file grows past ~80 lines. Keep stats-d's ROOT_CAUSE.md as a reference, but squash the code change into the stats-c PR. Stats-a's diff is subsumed. You would never have picked this from one agent's output alone.
How sidebar status actually behaves. The four coloured dots up top are herdr reading each agent's live output. working means it's producing tokens right now; blocked means it's showing a permission or select-an-option prompt and needs a human; idle means it's back at its input, ready for the next instruction — that's the state you poll with herdr wait agent-status <pane> --status idle. When an agent finishes and exits its shell, the pane drops to unknown, because there's no live output to read anymore — that isn't a bug; it's herdr telling you truthfully "there's no agent here now". The ground truth for "the work is done" is the branch tip: git -C <worktree> log --oneline -1.