Type: enhancement · Tier: deferred · Tool: `wait_for_text`
Problem
When `wait_for_text` polls a pane near `history-limit`, it emits a one-shot `ctx.warning` notification — "wait_for_text correctness is best-effort here. For deterministic synchronization use wait_for_channel." That signal routes only to MCP `notifications/message`. Clients that don't subscribe to log notifications (minimal stdio transports, agent loops that drop log messages, programmatic callers) receive a normal `WaitForTextResult` with `found`/`timed_out` populated but no structured indication that matching was best-effort.
The result: an agent gets back `found=True` or `found=False` and has no way to distinguish "polling was reliable" from "we were in the trim-risk band and the answer might be wrong" — exactly the information the runtime warning was designed to surface.
Proposed fix
Add a structured field to `WaitForTextResult`:
```python
class WaitForTextResult(BaseModel):
found: bool = ...
matched_lines: list[str] = ...
pane_id: str = ...
elapsed_seconds: float = ...
timed_out: bool = ...
risk_band_warned: bool = Field(
default=False,
description=(
"True if polling entered the history-limit trim-risk band "
"(top 10% of history_limit) at any point during the wait. "
"Indicates wait_for_text's match result is best-effort; "
"compose tmux wait-for -S with wait_for_channel for "
"deterministic completion."
),
)
```
The flag is already tracked inside `wait_for_text` as the local `warned_risk_band` bool used to gate the one-shot warning. Surface it on the returned model.
Trade-offs
- API shape addition to `WaitForTextResult`. Project is pre-alpha (`0.1.x`) so additive fields are not breaking, but the surface should be agreed on before shipping — once a field is in a public response model, removing it is a breaking change.
- Tests: extend the existing trim-risk-band tests (`test_wait_for_text_warns_in_history_limit_risk_band`, `test_wait_for_text_warns_when_already_in_risk_band`) to assert `result.risk_band_warned is True`. The non-risk-band tests should assert `result.risk_band_warned is False` to lock the default.
- Docs: the breaking-changes CHANGES entry already says "the tool emits a notifications/message warning when polling approaches history-limit". Add a sentence noting the structured-field equivalent for clients that don't subscribe to logs.
Why this is non-duplicative
Cross-checked against the existing deferred issues:
None of those touch the structured-result-vs-notification ergonomic split for `wait_for_text`. This issue is the standalone tracking point.
Type: enhancement · Tier: deferred · Tool: `wait_for_text`
Problem
When `wait_for_text` polls a pane near `history-limit`, it emits a one-shot `ctx.warning` notification — "wait_for_text correctness is best-effort here. For deterministic synchronization use wait_for_channel." That signal routes only to MCP `notifications/message`. Clients that don't subscribe to log notifications (minimal stdio transports, agent loops that drop log messages, programmatic callers) receive a normal `WaitForTextResult` with `found`/`timed_out` populated but no structured indication that matching was best-effort.
The result: an agent gets back `found=True` or `found=False` and has no way to distinguish "polling was reliable" from "we were in the trim-risk band and the answer might be wrong" — exactly the information the runtime warning was designed to surface.
Proposed fix
Add a structured field to `WaitForTextResult`:
```python
class WaitForTextResult(BaseModel):
found: bool = ...
matched_lines: list[str] = ...
pane_id: str = ...
elapsed_seconds: float = ...
timed_out: bool = ...
risk_band_warned: bool = Field(
default=False,
description=(
"True if polling entered the history-limit trim-risk band "
"(top 10% of history_limit) at any point during the wait. "
"Indicates wait_for_text's match result is best-effort; "
"compose tmux wait-for -S with wait_for_channel for "
"deterministic completion."
),
)
```
The flag is already tracked inside `wait_for_text` as the local `warned_risk_band` bool used to gate the one-shot warning. Surface it on the returned model.
Trade-offs
Why this is non-duplicative
Cross-checked against the existing deferred issues:
None of those touch the structured-result-vs-notification ergonomic split for `wait_for_text`. This issue is the standalone tracking point.