Skip to content

wait_for_content_change: surface pane death and respawn as ToolError for parity with wait_for_text #53

@tony

Description

@tony

Type: enhancement · Tier: deferred · Tool: wait_for_content_change

Problem

wait_for_text raises ToolError when the pane dies (#{pane_dead}=1), is respawned (#{pane_pid} changes), or has its history shrunk (clear-historyhistory_size drops below entry baseline). wait_for_content_change does none of this — it polls capture_pane() until content differs or timeout. If the pane dies mid-wait, the tool returns changed=False after the full timeout instead of surfacing the lifecycle event.

An agent using wait_for_content_change to confirm "the pane is doing something" has no signal that the underlying process has exited or been swapped. Same footgun the wait_for_text lifecycle detection was added to address — different tool, identical mechanism.

Proposed fix

Read a small per-tick state snapshot via one display-message round-trip:

"#{pane_pid}|#{pane_dead}"

Cache baseline_pid at entry. Re-read each tick. Raise ToolError on:

  • state.pane_dead == True — "pane {pane_id} died during wait" (same message/shape as wait_for_text)
  • state.pane_pid != baseline_pid — "pane {pane_id} was respawned during wait (pid X -> Y)"

No baseline-anchor math needed. wait_for_content_change's "any change anywhere" semantics are unaffected — the lifecycle check is orthogonal to the capture-diff comparison the tool already does.

Source pointers at tmux SHA 134ba6c

  • #{pane_dead} and #{pane_pid} are stable format strings (see format.c)
  • Same detection path wait_for_text already uses — verified via test_wait_for_text_raises_on_pane_death and test_wait_for_text_raises_on_pane_respawn

Trade-offs

  • Adds one display-message round-trip per tick to wait_for_content_change (currently the tool issues only capture_pane per tick). The cost is symmetric with wait_for_text — same number of subprocesses per poll.
  • Adds two regression tests (death + respawn) mirroring the existing wait_for_text ones.

Recommendation

Defer until an agent flow asks for it OR a small refactor opportunistically lands the parity. Filed as a deferred enhancement so the inconsistency doesn't get lost. The downstream wait_for_text PR documents the gap by analogy; this issue is the standalone tracking point.

Why this is non-duplicative

Cross-checked against the deferred wait-family issues (#50, #51, #52) and libtmux #671:

None of those address wait_for_content_change lifecycle parity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions