Skip to content

refactor(coding-agent): derive scoped heartbeats at render time - #1749

Closed
snimu wants to merge 8 commits into
snimu/on-demand-agent-peersfrom
snimu/derive-scoped-heartbeats
Closed

refactor(coding-agent): derive scoped heartbeats at render time#1749
snimu wants to merge 8 commits into
snimu/on-demand-agent-peersfrom
snimu/derive-scoped-heartbeats

Conversation

@snimu

@snimu snimu commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

What was wrong

The TUI stored a scoped heartbeats list — a projection of the heartbeat catalog x connection state x subagent snapshots — kept aligned by updateScopedHeartbeats() calls scattered across unrelated code paths. A missed call site meant stale heartbeat counts or manager rows (audit: dup-truth.md finding 5; TUI-side sibling of #1743).

The fix

The stored projection, its updater, and setHeartbeats() are deleted. The tray label, refresh scheduler, and heartbeat manager derive the scoped list from the three sources at use/render time; the manager holds only selection state by heartbeat ID (re-anchoring gracefully when the selected entry disappears). Production code is net deletion; stale test stubs of the deleted method removed.

How it's verified

Reviewer accounted for all 4 former sync call sites, bounded the per-render derivation cost (tiny, overlay-scoped), traced selection survival through catalog refreshes, and confirmed the getter wiring holds no leak. Focused suites 190/190; full CI-style failing set exactly matches the stack base. Two-model implement/review loop.

Stacked on #1748 (test the whole stack at the leaf; merge base-first).

Note: intentionally no Linear ticket for this cleanup stack, so that check stays red.


Note

Low Risk
TUI-only refactor that removes duplicate state; behavior should improve when scope changes, with no security or persistence impact.

Overview
Removes the cached scoped heartbeats list and updateScopedHeartbeats() sync calls from interactive mode. The tray label, refresh scheduler, and heartbeat manager now call getScopedHeartbeats() (catalog × connection state × subagent snapshots) when they need the list.

HeartbeatManagerComponent no longer takes a static array or setHeartbeats. It receives a getHeartbeats callback and reads the current scoped set on each render. List selection is tracked by heartbeat id instead of array index, with render-time re-anchoring when entries disappear or reorder.

Connection state and subagent updates schedule a manager refresh instead of pushing an updated list. Tests cover live list updates on render and the new scoping path.

Reviewed by Cursor Bugbot for commit e953a58. Bugbot is set up for automated code reviews on this repo. Configure here.

Linear ticket: ENG-5665
(ticket linked above)

Note

Derive scoped heartbeats at render time in HeartbeatManagerComponent

  • Replaces the static heartbeat list passed to HeartbeatManagerComponent with a getHeartbeats callback that pulls the current scoped set on each render.
  • Adds InteractiveMode.getScopedHeartbeats as the single source of truth for heartbeat scoping; removes the cached this.heartbeats array and the updateScopedHeartbeats method.
  • Switches selection tracking from array index to heartbeat id, so the selected item persists across reorders and removals. The render loop auto-corrects selection (and exits the actions view) when a heartbeat no longer exists.
  • Connection state and subagent summary updates now schedule a heartbeat manager refresh instead of immediately recomputing and pushing a list.
  • Risk: callers that constructed HeartbeatManagerComponent with an initial heartbeats array or called setHeartbeats must migrate to the getHeartbeats callback — the old constructor signature and setHeartbeats method are removed.

Macroscope summarized e953a58.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 972c96b. Configure here.

Comment thread packages/coding-agent/src/modes/interactive/interactive-mode.ts
@snimu

snimu commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #1830: GitHub's stack lock prevents retargeting stacked PRs, so this PR was recreated as a plain PR against main (same branch, same content, all review threads here are resolved). Please review/merge #1830 instead.

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