Automation patterns: wait for tmux instead of guessing - #734
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #734 +/- ##
==========================================
- Coverage 52.45% 52.40% -0.06%
==========================================
Files 26 26
Lines 3729 3729
Branches 747 747
==========================================
- Hits 1956 1954 -2
- Misses 1469 1472 +3
+ Partials 304 303 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
a09ab07 to
d4c8f7f
Compare
Code reviewFound 1 issue, now fixed in d4c8f7f:
Lines 62 to 67 in a09ab07 The same hunk shipped the literal placeholder 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
80c8797 to
3f81cf8
Compare
Code reviewFound 1 issue, fixed in 3f81cf8:
The prose now says what the tag actually does — it separates the command's output from the shell's echo, not one command's output from the last one's — and the failing command clears the pane first, so 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
3f81cf8 to
5d304cb
Compare
Code reviewFound 1 issue, fixed in 5d304cb:
Worth noting for the record: under a full-suite 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
c5aa46c to
21de528
Compare
why: The examples slept a fixed amount and then read the pane. Measured, send_keys to visible in capture_pane is 100ms at the median under a parallel test run, so the 100ms sleeps had no headroom at all -- the "Capturing output between markers" example fails deterministically at --reruns 0 today, and the repo default of --reruns=2 hides it. Several checks were also searching the joined capture, which matches the command tmux echoed onto the pane and is true before the shell has run. what: - Have commands signal a tmux channel and block on Server.wait_for, which returns when the command is actually done - Compare whole captured lines instead of searching the joined capture - Keep sleeps only where the example is about elapsed time itself
why: The page's examples were failing at `--reruns 0` before the rewrite, so a reader copying them got the flake too. what: - Record the automation-patterns rewrite under `Documentation`.
21de528 to
8d35933
Compare
Summary
automation-patternsthat fails deterministically today at--reruns 0, hidden by the repo's--reruns=2default.Server.wait_for()— which returns the moment the command is done rather than after a guess.capture_pane()returns the command tmux echoed onto the pane.send_keys,capture_paneandServer.wait_for, all of which ship today.Why the sleeps could not work
Measured on this branch:
send_keysto visible incapture_pane()is p50 100.7 ms underpytest -n auto, p90 130 ms. The page usedtime.sleep(0.1). That is roughly -1 ms of headroom at the median.The bug this fixes is live
docs/topics/automation_patterns.mdonmaster, four consecutive runs at--reruns 0:Same command on this branch:
The failing example is "Capturing output between markers", whose helper searches
'\n'.join(pane.capture_pane())for a marker the command itself contains — so it matches the echoed command line and returns before the command has produced anything. ItsTimeoutErrorbranch is unreachable. The page's own assertion then passes off the echo.The two changes
Signal a channel, block on it. tmux remembers a signal sent before the waiter starts, so there is no lost-wakeup race regardless of ordering. Measured: a pane running
sleep 1.5; tmux wait-for -S <ch>released the waiter after 1.506 s, with no polling; signalling first and then waiting returned in 3 ms.Compare whole lines.
capture_pane()already returnslist[str]; joining it and searching for a substring is what lets the echo satisfy the check. Demonstrated withenter=False, so no shell ever runs:Sleeps remain only where an example is about elapsed time itself.
Test plan
docs/topics/automation_patterns.mdgreen 4/4 at--reruns 0, against 0/4 onmasteruv run ruff check ./uv run ruff format ./uv run mypycleanuv run py.test --reruns 0cleanjust build-docsclean, no new warningsNote for the merger
The
CHANGESheading cites(#NN)— swap it for this PR's number on merge. It will conflict with the sibling PRs for #723, #724, #725, #726 and #731, which all add to the same block; keep both sides.Related but not required:
Server.wait_for()still has no timeout (#732), so a command that dies before signalling blocks forever. That does not affect the examples here, all of which signal on every exit path, but it is worth closing before this pattern is recommended more widely.