fix(bin): capture the full viewport for Herdr composer reads so a slash-command popup cannot hide the composer - #5876
Conversation
Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533
f24d86d to
358af97
Compare
|
Speaking as Kun's firstmate: Verdict: Whole thread + tip vs main Tip vs main: Herdr adapter composer state/content reads switch to full visible viewport ( contract-class: restore — concrete existing Herdr submit/exit path broken when slash menu taller than the 20-row tail. VISION.md (each rule)
Attestation: MATCH |
|
Speaking as Kun's firstmate: CI SUCCESS |
|
Speaking as Kun's firstmate: this is merged. Thank you @andrewesweet — really appreciate you taking the time on this. |
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
…sh-command popup cannot hide the composer (kunchenguid#5876) * Fix Herdr composer reads blinded by the slash-command popup Capture the full visible viewport for every Herdr composer state and content read instead of a bounded tail. Claude Code renders its slash-command popup between the composer and the pane bottom, which pushes the composer outside a tail window. The pre-Enter payload proof then read an empty composer, judged a typed command unsent, and cleared it without pressing Enter. The proof-lines value now bounds only the clear cost, not the capture size. Growing the window adds rows above the composer only, so bottom-most shape selection and prior verdicts are unchanged. The suffix refusal is kept, and the shared inbox pending-line read stays a bounded tail. Portable regressions cover the popup-below-composer layout, and the live submit-confirmation guard gains a third exit scenario. The runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run. Closes kunchenguid#5533 * no-mistakes(document): Clarify composer capture bound ownership * no-mistakes(review): Drop unrequired bracketed-paste Enter fallback from live guard * no-mistakes(review): Latch trust prompt, check idle composer arm first
Intent
Herdr composer reads capture the full visible viewport instead of a bounded tail, so a tall Claude Code slash-command popup no longer hides the composer row.
On Claude Code 2.1.283 the slash-command popup renders about 19 menu rows between the composer and the pane bottom, which pushes the composer outside the Herdr adapter's 20-row tail capture.
The pre-Enter payload proof then reads an empty composer, judges a typed
/exitunsent, clears it with Ctrl+U, and reports a failed send without pressing Enter, so a controlled exit of a Claude worker on Herdr never exits it.The Herdr adapter's own composer state and content reads (
fm_backend_herdr_composer_stateandfm_backend_herdr_composer_content) now capture the visible viewport, while the shared steering-inbox composer read stays bounded, and the proof-lines value becomes a bound on clear cost rather than on capture size.Growing the window only adds rows above the composer, so the bottom-most shape selection and every previously passing verdict are unchanged, and the suffix refusal from #5336 is kept.
fm_backend_herdr_composer_contentdrops its optional line-count argument; all callers are insidebin/backends/herdr.sh.Portable regressions cover the popup-below-composer layout, the live submit-confirmation test gains a third
/exitscenario, and the runtime-backends verification record documents the Herdr 0.9.0 and Claude Code 2.1.283 run.Closes #5533.
What Changed
fm_backend_herdr_composer_stateandfm_backend_herdr_composer_contentnow read the pane's full visible viewport (pane read --source visible, styled via the newfm_backend_herdr_visible_capture_ansi, replacing the boundedfm_backend_herdr_capture_ansi), so Claude Code 2.1.283's ~19-row slash-command popup can no longer push the composer row outside a 20-row tail. Previously the pre-Enter payload proof read an empty composer, judged a typed/exitunsent, cleared it with Ctrl+U, and returnedsend-failedwithout pressing Enter.fm_backend_herdr_composer_contentdrops its optional line-count argument;fm_backend_herdr_proof_linesnow only bounds the Ctrl+U clear presses, not a capture size.FM_COMPOSER_CAPTURE_LINESkeeps bounding the tail-capture adapters and the shared steering-inbox composer read; its comment,docs/configuration.md,docs/herdr-backend.md, and the runtime-backends verification record state the new ownership split and the dated Herdr 0.9.0 / Claude Code 2.1.283 measurement.tests/fm-backend-herdr.test.shbuild a popup-below-composer screen and assert both thependingstate verdict and a single submitted Enter with no--linesread; the opt-in live guard gains a third scenario that types/exitbehind its popup and requires the Claude process to exit.Closes #5533.
🤖 Generated with Claude Code
Risk Assessment
✅ Low: Well-bounded root-cause fix: two herdr composer reads swap a bounded tail for the already-verified viewport primitive, the removed helper and dropped argument have no surviving callers, and the shared classifier's refusal gates all key off rows below the selected shape so added rows above cannot change a prior verdict.
Testing
Stood up throwaway Herdr labs through bin/fm-herdr-lab.sh and drove real Claude Code 2.1.283 on herdr 0.9.0. The repo's live submit-confirmation guard passed all three scenarios, including the new one that types
/exitbehind Claude's command popup and requires the agent to actually exit. A second live lab captured the real pane: the composer sits at viewport row 15 of 37 with 20 popup rows below it, so the old 20-row tail window (rows 18-37) excludes it; on that same live pane the base-commit bounded read returned an empty composer andunknownstate while the target-commit viewport read returned/exitandpending, then the submit path landed Enter and Claude exited. The two new portable regressions pass on the target commit and fail on the base commit. Visual evidence is a rendered PNG of the captured live pane screen with row numbers; the product surface here is a terminal pane, so the pane capture is the end-user view. The suffix-only truncated-read-back refusal (#5336) was never driven against the live CLI — only stubbed-transport regressions cover it — so it is reported untested.fm_backend_herdr_composer_contentreturned/exitandcomposer_statereturnedpending(live-clau…fm_backend_herdr_composer_contentreturned[]andcomposer_statereturnedunknownagainst the identical live pane holding the typed/exit(live-composer-read-base-vs-fi…fm_backend_herdr_send_text_submitreportedemptyand the requested token rendered in the real Claude pane (live-submit-confirm-guard.log)tests/fm-backend-herdr.test.shfor this path, never a live run, so no live result exists. Driving it live needs a way to force the…Evidence: Same pane capture as plain text
Source: Same pane capture as plain text
Evidence: The old bounded 20-row tail of that capture (composer row absent)
Source: The old bounded 20-row tail of that capture (composer row absent)
Evidence: Base vs fixed composer read on the same live pane
Source: Base vs fixed composer read on the same live pane
viewport_rows=37 composer row = 15 old bounded tail window = rows 18..37 (composer excluded) FIXED (target commit, --source visible) composer_content=[/exit] composer_state=pending BASE (fba81cb, bounded --lines tail) composer_content=[] composer_state=unknown submit_verdict=unknown (Enter landed; post-Enter read fails because Claude exited) agent_exited=1Evidence: Live submit-confirmation guard transcript
Source: Live submit-confirmation guard transcript
ok - live Herdr submit confirm: Claude Code (2.1.283 (Claude Code)) on herdr 0.9.0 reports empty and renders the requested reply in isolated session fm-lab-herdr-submit-con-1927591-23935 ok - live Herdr submit confirm: Claude Code (2.1.283 (Claude Code)) on herdr 0.9.0 submits a U+2063 away-supervisor payload whose read-back drops the mark ok - live Herdr submit confirm: Claude Code (2.1.283 (Claude Code)) on herdr 0.9.0 proves and submits a typed /exit behind its command popupEvidence: Claude pane after the submitted /exit (agent gone, shell prompt back)
Source: Claude pane after the submitted /exit (agent gone, shell prompt back)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
fm_backend_herdr_composer_contentreturned/exitandcomposer_statereturnedpending(live-clau…fm_backend_herdr_composer_contentreturned[]andcomposer_statereturnedunknownagainst the identical live pane holding the typed/exit(live-composer-read-base-vs-fi…fm_backend_herdr_send_text_submitreportedemptyand the requested token rendered in the real Claude pane (live-submit-confirm-guard.log)tests/fm-backend-herdr.test.shfor this path, never a live run, so no live result exists. Driving it live needs a way to force the…FM_HERDR_SUBMIT_CONFIRM_LIVE=1 bash tests/fm-herdr-submit-confirm-live-e2e.test.sh(real Claude Code 2.1.283 in an isolated fm-lab-* Herdr session; three live scenarios)Manual live lab: typed/exitinto the real composer, captured the visible viewport, then comparedfm_backend_herdr_composer_content/composer_statefrom the target commit against the same functions from base commit fba81cb on the same live paneManual live lab: cleared the composer, ranfm_backend_herdr_send_text_submit <target> /exit 3 0.4 1.2, confirmed the agent exited and the pane fell back to the shellbash tests/fm-backend-herdr.test.sh(portable adapter suite, includes the two new popup-layout regressions)Fail-before check: ran the new portable regressions against agit archiveof base commit fba81cb —not ok - a composer above a slash-command popup must read pending, got 'unknown'docs/verification/runtime-backends.md:1167- The dated record states "Verified live in the lab: with the popup up the state read answerspending(previouslyempty) and the payload proof returns/exit... and the Claude process exits", while this run's test phase recorded the live verdict as inconclusive (the/exitscenario was not driven live; declined as test round 1test-1, and review round 3popup-fixture-rule-pair-is-load-bearing-and-unverifiedflagged the same missing evidence for the popup's rule-pair shape). Either the claim rests on an earlier lab run not reproduced here, or it should be softened to the measured popup geometry plus the portable regressions. Left unchanged because both underlying findings are recorded user decisions, and rewriting the record's verification claim would contradict them.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.