Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3
feat: add --scope cursor-line render wait predicate#169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
ea2ff13
feat: add --scope cursor-line render wait predicate
ThomasK33 d0c8eef
chore: bump overrides to clear high-severity audit advisories
ThomasK33 fc5d112
docs: anchor prompt regex without trailing space in cursor-line examples
ThomasK33 8501e4d
chore: relock aube after upstream repo transfer
ThomasK33 86ea1d5
chore: merge CI setup/audit fixes to unblock checks
ThomasK33 de2720d
docs: teach cursor-line waits in the canonical runtime skill
ThomasK33 4bcc205
docs: anchor standalone cursor-line waits with --after-seq
ThomasK33 a734752
docs: record the cursor-line wait scope decision as ADR 0010
ThomasK33 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -90,6 +90,7 @@ Use `wait` to synchronize on terminal state: | ||
| ```bash | ||
| agent-tty wait <session-id> --text 'ready' --json | ||
| agent-tty wait <session-id> --regex 'READY|DONE' --json | ||
| agent-tty wait <session-id> --regex 'READY>$' --scope cursor-line --json | ||
| agent-tty wait <session-id> --screen-stable-ms 1000 --json | ||
| agent-tty wait <session-id> --idle-ms 500 --json | ||
| agent-tty wait <session-id> --exit --json | ||
| @@ -99,13 +100,34 @@ Useful flags: | ||
| - `--text <string>`: wait for text to appear in rendered output. | ||
| - `--regex <pattern>`: wait for a regex match in rendered output. | ||
| - `--scope <scope>`: where `--text`/`--regex` match — `screen` (default, whole visible screen) or `cursor-line` (only the row the cursor is on). See [Echo-Match](#echo-match). | ||
| - `--screen-stable-ms <ms>`: wait for the rendered screen to be stable. | ||
| - `--after-seq <n>`: only match renderer snapshots produced after this Event Log sequence — thread an input command's returned `seq` here so the wait cannot match pre-input screen state. | ||
| - `--idle-ms <ms>`: wait for output idleness. | ||
| - `--exit`: wait for the process to exit. | ||
| - `--timeout <ms>`: maximum wait time in milliseconds, with `0` meaning infinite. | ||
| On timeout, a standalone `wait` exits `11` (`WAIT_TIMEOUT`) while preserving a success JSON envelope with `timedOut: true` in the result (`matched: false` for render waits). Inside `batch`, a timed-out `wait` step is a step failure with the same `WAIT_TIMEOUT` exit code under fail-fast. | ||
| ### Echo-Match | ||
| A whole-screen `wait` can be satisfied by the terminal's **echo of a just-typed command**: `run <sid> 'echo Done'` followed by `wait --text Done` matches the echoed command line itself, not the command's output. Use `--scope cursor-line` to restrict `--text`/`--regex` matching to the row the cursor is currently on. Once Enter is pressed the cursor moves past the echoed line, so a cursor-line wait cannot match the echo. It is ideal for waiting on prompts, which render exactly at the cursor: | ||
ThomasK33 marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ```bash | ||
| agent-tty wait <session-id> --regex 'READY>$' --scope cursor-line --json | ||
| ``` | ||
| Rendered lines are right-trimmed of trailing ASCII spaces, so anchor prompt regexes without the trailing space: a prompt displayed as `READY> ` matches `READY>$`, not `READY> $`. | ||
| A standalone cursor-line wait issued right after an input command (`type`, `send-keys`, `run --no-wait`) can still match the **pre-input screen**: input commands return once the input is logged, before the application's response is necessarily rendered. If the cursor row already matched before the input — for example a repeated prompt in an echo-disabled application — the wait returns without the application having responded. Thread the input command's returned `seq` into `--after-seq` so the wait only observes screen state produced after the input; inside `batch`, wait steps get this anchoring automatically from the Wait Baseline: | ||
| ```bash | ||
| SEQ=$(agent-tty send-keys <session-id> Enter --json | jq -r '.result.seq') | ||
| agent-tty wait <session-id> --regex 'READY>$' --scope cursor-line --after-seq "$SEQ" --json | ||
| ``` | ||
| For waiting on output text that scrolls past the cursor, prefer a distinctive output token or combine `--text` with `--screen-stable-ms`. | ||
| ### Screen Hash | ||
| `snapshot` results (both `--format structured` and `--format text`) and a **matched** `wait` result carry an optional `screenHash`: a lowercase 64-character hex SHA-256 of the visible screen text. Compare it across two calls to tell whether the visible screen actually changed — equal hashes mean identical visible content, even if the event-log sequence advanced on a no-op repaint. | ||
| @@ -142,7 +164,7 @@ Steps are a JSON array; each step is exactly one verb. The shape mirrors the res | ||
| - `type` / `paste`: a string of literal text. | ||
| - `sendKeys`: a non-empty array of key names — individual named keys or single characters (e.g. `["Enter"]`, `["Ctrl+C"]`, `["Escape", "Enter"]`). Multi-character literal text such as `:wq` is not a key name; send it with a `type` step. | ||
| - `run`: a command string, with optional `noWait` (fire-and-forget) and `timeout` (ms). A `run` step is a waited run by default. | ||
| - `wait`: the same conditions as the `wait` command — `text`, `regex`, `screenStableMs`, `cursorRow`, `cursorCol`, and `timeout` (ms). | ||
| - `wait`: the same conditions as the `wait` command — `text`, `regex`, `scope`, `screenStableMs`, `cursorRow`, `cursorCol`, and `timeout` (ms). | ||
| Input source and flags: | ||
| @@ -186,7 +208,7 @@ The `--json` result is a per-step envelope: | ||
| Each step record carries its `index`, `kind`, `status` (`completed` | `failed` | `not-run` | `interrupted`), and `durationMs`. Input steps report the Event Log `seq` they produced; `wait` steps report the `waitBaseline` they were anchored to plus `matched` / `timedOut` / `matchedText` / `capturedAtSeq`, and a matched `wait` step also carries the `screenHash` of the screen it observed (see [Screen Hash](#screen-hash)). `completedCount` and `failedIndices` summarize the run. A fail-fast batch exits non-zero with the failed step's exit code (e.g. `11` for a `WAIT_TIMEOUT`); `--keep-going` exits `1` if any step failed. If the process is interrupted by SIGINT/SIGTERM, batch flushes the same envelope with the in-flight step marked `interrupted` and later steps `not-run`, then exits non-zero. | ||
| The Wait Baseline fixes stale-match only. It does **not** fix echo-match: a `wait` can still match the terminal's echo of a just-typed command (the echo renders _after_ the baseline). Use a distinctive output token or a `screenStableMs` wait rather than waiting for text you just typed. Interrupting a batch mid-`wait` leaves that wait's command still running on the session (the wait is abandoned, not cancelled), exactly like a caller timeout on `run`. | ||
| The Wait Baseline fixes stale-match only. It does **not** fix echo-match: a whole-screen `wait` can still match the terminal's echo of a just-typed command (the echo renders _after_ the baseline). Use `"scope": "cursor-line"` on the wait step to restrict matching to the cursor row (see [Echo-Match](#echo-match)), or wait for a distinctive output token. Interrupting a batch mid-`wait` leaves that wait's command still running on the session (the wait is abandoned, not cancelled), exactly like a caller timeout on `run`. | ||
| ## Screenshots And Recording Exports | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| --- | ||
| status: accepted | ||
| --- | ||
| # Render waits accept a cursor-line scope to defeat echo-match | ||
| ## Context | ||
| ADR 0007 gave **Render Waits** an optional **Wait Baseline** (`afterSeq`) and | ||
| deliberately left _echo-match_ unsolved: a `wait --text "foo"` can match the | ||
| terminal's **echo of a just-typed command** because the echo renders _after_ | ||
| the baseline. Both ADR 0007 and the batch PRD declared echo-match the caller's | ||
| concern (use a distinctive output token or `screenStableMs`). | ||
| That workaround is weak for the most common wait target: a prompt. Prompts | ||
| often reproduce text the caller just typed, and `screenStableMs` trades | ||
| correctness for latency and can still accept a stalled-but-wrong screen. | ||
| ## Decision | ||
| A **Render Wait** text/regex condition accepts an optional **scope**: | ||
| `screen` (default, the whole visible screen — prior behavior) or | ||
| `cursor-line` (only the row the cursor is on). Once Enter is pressed the | ||
| cursor moves past the echoed line, so a `cursor-line` wait cannot match the | ||
| echo. Prompts render exactly at the cursor, making them the intended target. | ||
| - `scope` is added to `WaitForRenderParams` and batch wait steps; it requires | ||
| `text` or `regex`. | ||
| - The matcher evaluates `cursor-line` conditions against | ||
| `visibleLines[cursorRow]`, which is right-trimmed of trailing ASCII spaces | ||
| like every rendered line. | ||
| - With no `scope` a wait behaves exactly as before, so the change is backward | ||
| compatible. | ||
| This amends the echo-match consequence of ADR 0007: echo-match now has a | ||
| first-class remedy. The **Wait Baseline** remains the stale-match remedy, and | ||
| the two compose — a standalone `cursor-line` wait issued right after an input | ||
| command should still thread that input's `seq` into `--after-seq`, because | ||
| input RPCs return before the application's response necessarily renders. | ||
| ## Consequences | ||
| - Prompt waits are echo-safe without inventing distinctive output tokens or | ||
| paying `screenStableMs` latency. | ||
| - Waiting on output that scrolls past the cursor still needs a distinctive | ||
| token or screen stability; `cursor-line` is a prompt-shaped tool. | ||
| - One optional enum grows the protocol and matcher surface. | ||
| ## Alternatives considered | ||
| - **Keep echo-match the caller's concern (status quo).** Rejected: the | ||
| workaround fails precisely on prompts, the most common wait target. | ||
| - **Exclude the echoed input line by diffing against a pre-input capture.** | ||
| Rejected: heuristic, breaks when output legitimately repeats the input, and | ||
| does not use the canonical event-log/cursor state. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.