Skip to content

feat(herdr): highlight the active space and alert when an agent waits - #87

Merged
barbatdev merged 1 commit into
mainfrom
feat/herdr-active-space
Oct 30, 2026
Merged

barbatdev merged 1 commit into
mainfrom
feat/herdr-active-space

Conversation

@barbatdev

Copy link
Copy Markdown
Owner

Summary

  • Active space row: solid brand violet (#7127FF) background, semibold name in the solid foreground.
  • Git branch and ahead/behind now sit on a second line under the space name (48px rows).
  • Waiting alert: spaces whose agents are blocked get a pulsing 2px border and a "● te espera" pill; machine headers show "● N" so collapsed groups still alert. The 600ms pulse timer only runs while something is blocked. Colors come from the Herdr theme blocked token.

Test plan

  • node --check on the mod
  • Screenshots on Herdr Desktop with a simulated blocked space (both pulse frames), simulation reverted

🤖 Generated with Claude Code

https://claude.ai/code/session_01A9D7ph123Jn8iB1eGbr8Nz

- Active space row uses the solid brand violet with solid foreground text.
- Git branch and ahead/behind move to a second line under the space name.
- Spaces with a blocked agent get a pulsing border and a "te espera" pill;
  machine headers show a waiting count so collapsed groups still alert.
- The pulse timer only runs while some space is blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9D7ph123Jn8iB1eGbr8Nz
@barbatdev
barbatdev merged commit 4857410 into main Oct 30, 2026
1 check passed
@barbatdev

Copy link
Copy Markdown
Owner Author

Fleet review (deepseek)

Lens: evidence + test design. The diff does what the body describes: the active row uses the theme's solid/solid_foreground tokens, git details move to a second line with the row height derived from hasGitTail, blocked spaces get a pulsing blocked-color border plus a "te espera" pill, folded machine headers get a waiting count, and the 600 ms pulse timer returns early when nothing is blocked (main.js:74-79). I checked the two behavioural edges that could break: the pulse stops and clears on the tick after the last blocked space, and rowHeight is only consumed by row(), so the 48 px rows cannot desynchronise any index math (reordering still uses row indexes, not pixels). Remaining findings are evidence questions and small nits, not defects: the header count the body advertises is unreachable in the narrow rail, the height decision has no automated coverage, and the pulse re-renders the whole panel twice a second for as long as an agent waits.

Suggestion (4)

  • A blocked space re-renders the whole panel twice a second for as long as it waits (herdr/desktop/mods/refactoria-spaces/main.js:74): Every tick while a space is blocked calls cx.notify(), and render() re-reads spaces(), machines() and, through ordered(), panes() — the file's own comment at line 23 notes each panes() read copies every pane. A blocked agent normally waits for a human for minutes or hours, so this is a permanent 2 Hz full-panel re-render, not a burst. If the space list already exposes an aggregate you could derive waiting from without the extra reads, or if the panel can be re-rendered from a cached ordered() while only the pulse flag changes, that would keep the alert and drop the cost.
  • Header border width toggles with the pulse and shifts its content (herdr/desktop/mods/refactoria-spaces/main.js:254): border(waiting ? 2 : 1) changes the box width when a group starts or stops waiting, so the machine name, the waiting count, the status dot and the chevron jump 2 px at the start and end of an alert (and the row content area shrinks). The space rows avoid this by always using border(2) while waiting. Reserving the 2 px unconditionally, or pulsing only the colour on a constant 2 px border, keeps the header from reflowing.
  • The contrast comment overstates which colours fail (herdr/desktop/mods/refactoria-spaces/main.js:305): The comment says dim and status colours fall under 4.5:1 on the solid row. Against the shipped theme (herdr/desktop/themes/refactoria.json) dim #F2EFFA on solid #7127FF measures 5.38:1, which passes; the ones that fail are ansi2 (3.87:1) and ansi1 (2.25:1). So swapping the git tail to solid_foreground was not needed for dim, and the tree branch icon at line 349 still uses t.dim on the active row. Either narrow the comment to the ahead/behind deltas it actually protects, or say why dim was replaced too.
  • where in gitTail shadows the module-level where() helper (herdr/desktop/mods/refactoria-spaces/main.js:299): const where = this.gitWhere(…) shadows the where(s, ps) function defined at line 30 that the rest of the file uses to build git map keys. Inside gitTail any future call to where(…) would resolve to the string and fail silently in a way that is easy to misread during review. gitLabel or line would keep the helper reachable.

Question (3)

  • Header waiting count never renders in the narrow rail (herdr/desktop/mods/refactoria-spaces/main.js:262): The body says the machine header shows "● N" so collapsed groups still alert. The badge is chained off .when(!collapsed, …) (line 262) and collapsed is narrow() (< 160 px sidebar, line 20, 375), so in the rail the header renders only the machine icon: no count, no status dot, no chevron. Folded groups do get the count, so the umbrella claim holds for folding only. Which did you mean by "collapsed", and what evidence covers the rail case?
  • The single-line/double-line decision has no automated evidence (herdr/desktop/mods/refactoria-spaces/main.js:294): rowHeight (line 29) now returns 48 whenever hasGitTail is true, and hasGitTail depends on gitWhere, which suppresses the branch when it equals the space name and suppresses master/main, and on ahead/behind from parsed --porcelain=v2 output. The test plan is node --check plus screenshots, and the repo has no harness for this mod. Missing conditions with expected outcomes: (a) worktree whose name equals its branch plus ahead-only, expect one line with "↑N"; (b) plain checkout on main, expect one line and 30 px; (c) detached HEAD (branch null), expect the literal "detached" and therefore a 48 px row; (d) behind-only, expect "↓N" and 48 px; (e) a blocked space with no git tail, expect the pill on a 30 px row. Which of these did the screenshots cover?
  • Pulse lifecycle assertions are absent from the test plan (herdr/desktop/mods/refactoria-spaces/main.js:74): The invariant worth pinning is the one you wrote in the comment: the timer only re-renders while something is blocked. Concretely: with no blocked space, spaces() is read but cx.notify() never fires; after the last blocked space clears, exactly one more tick sets this.pulse = false and notifies so the border disappears (line 76-78); while a space stays blocked the border width stays 2 and only its colour alternates. The screenshots cover the two frames, not the stop path. Can you confirm the stop path was exercised (unblock and watch the border disappear), or add it to the test plan?

Verdict: ready to merge

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant