Summary
A consolidated follow-up collecting the remaining agent-automation-bridge drivability/observability gaps surfaced while dogfooding the bridge through the recent feature PRs. #3819 (Phase-2 fidelity) closed the big ones — closed-menu reachability, slice tx, key ptt/mox, lineedit submit, resize, multi-instance — and #3826 deferred widget click/toggle out of the socket callback. These five are what's left, each found by the PR noted.
Gaps
1. TX-safety deny-word is an unanchored substring match ⚠️ correctness
isTransmitAction (AutomationServer.cpp) flags an action as transmit-keying via a bare contains() on the deny-words mox / ptt / transmit / cwx. An RX-only weather action with objectName aprsSvcWXBOT → aprssvcwxbot contains cwx (the c from svc + wx from wxbot) → falsely blocked. It's fail-safe (over-blocks, never under-blocks), so not a safety hole — but it's a real false-positive, and #3819's closed-menu reachability widened the action surface it scans, so collisions are now more likely.
Fix: anchor the deny-words to word/token boundaries (or require an explicit kTxKeyingProperty marker rather than the name-match fallback). (Surfaced in #3828; worked around there with an aprsService… spelling.)
2. Can't drive a QToolButton popup menu (macOS crash)
A synthetic click() on a QToolButton with a menu runs inside the socket-read callback; showing the menu's native popup window from there re-enters the Cocoa stack and segfaults intermittently (QMenu::popup → QCocoaWindow::setVisible). singleShot(0) deferral didn't help — showing the native window is the hazard. #3826 deferred widget click, but the popup show is still unsafe.
Fix: an openMenu/showMenu <button> verb that posts the menu show onto the GUI event loop. (Surfaced in #3828; worked around with pure InstantPopup + closed-menu action triggers.)
3. No mouse-drag / gesture synthesis verb
The bridge can invoke button-style actions but can't synthesize a press-move-release drag, so resize grips and slider handles can't be exercised end-to-end (only their persisted side-effects are checkable).
Fix: a drag <target> dx dy (or mouse <target> down/move/up) verb. (Surfaced in #3824 — the CW panel resize grip.)
4. Quindar firing isn't observable
No quindarPhase/quindarActive field in any get snapshot and ClientQuindarTone has no log category — the only proxy is deferred-unkey timing, so the tone and the quindarActiveChanged chip flash can't be asserted.
Fix: add quindarPhase/quindarActive to the get transmit snapshot, or an lcQuindar log line on intro/outro start. (Surfaced in #3798.)
5. Overlay-derived state isn't in dumpTree/get snapshots
GPU-overlay state drawn in SpectrumWidget (e.g. SliceOverlay::splitPartnerId, the split-pair marker) isn't reflected in dumpTree, so it can only be checked by pixel-grabbing.
Fix: expose splitPartnerId (and similar overlay-derived state) in a get pan/get slice snapshot so split-pairing etc. is assertable without image diffing. (Surfaced in #3794.)
Priority
#1 is the only correctness item (a real, if fail-safe, TX-guard false-positive) and is the most worth doing. #2–#5 are drivability/observability conveniences that would let future feature PRs prove themselves headlessly without per-PR workarounds.
Refs #3646, #3819, #3826. cc @jensenpat (bridge author).
Summary
A consolidated follow-up collecting the remaining agent-automation-bridge drivability/observability gaps surfaced while dogfooding the bridge through the recent feature PRs. #3819 (Phase-2 fidelity) closed the big ones — closed-menu reachability,
slice tx,key ptt/mox, lineeditsubmit,resize, multi-instance — and #3826 deferred widget click/toggle out of the socket callback. These five are what's left, each found by the PR noted.Gaps
1. TX-safety deny-word is an unanchored substring match⚠️ correctness
isTransmitAction(AutomationServer.cpp) flags an action as transmit-keying via a barecontains()on the deny-wordsmox/ptt/transmit/cwx. An RX-only weather action with objectNameaprsSvcWXBOT→aprssvcwxbotcontainscwx(thecfromsvc+wxfromwxbot) → falsely blocked. It's fail-safe (over-blocks, never under-blocks), so not a safety hole — but it's a real false-positive, and #3819's closed-menu reachability widened the action surface it scans, so collisions are now more likely.Fix: anchor the deny-words to word/token boundaries (or require an explicit
kTxKeyingPropertymarker rather than the name-match fallback). (Surfaced in #3828; worked around there with anaprsService…spelling.)2. Can't drive a
QToolButtonpopup menu (macOS crash)A synthetic
click()on aQToolButtonwith a menu runs inside the socket-read callback; showing the menu's native popup window from there re-enters the Cocoa stack and segfaults intermittently (QMenu::popup → QCocoaWindow::setVisible).singleShot(0)deferral didn't help — showing the native window is the hazard. #3826 deferred widget click, but the popup show is still unsafe.Fix: an
openMenu/showMenu <button>verb that posts the menu show onto the GUI event loop. (Surfaced in #3828; worked around with pureInstantPopup+ closed-menu action triggers.)3. No mouse-drag / gesture synthesis verb
The bridge can
invokebutton-style actions but can't synthesize a press-move-release drag, so resize grips and slider handles can't be exercised end-to-end (only their persisted side-effects are checkable).Fix: a
drag <target> dx dy(ormouse <target> down/move/up) verb. (Surfaced in #3824 — the CW panel resize grip.)4. Quindar firing isn't observable
No
quindarPhase/quindarActivefield in anygetsnapshot andClientQuindarTonehas no log category — the only proxy is deferred-unkey timing, so the tone and thequindarActiveChangedchip flash can't be asserted.Fix: add
quindarPhase/quindarActiveto theget transmitsnapshot, or anlcQuindarlog line on intro/outro start. (Surfaced in #3798.)5. Overlay-derived state isn't in
dumpTree/getsnapshotsGPU-overlay state drawn in
SpectrumWidget(e.g.SliceOverlay::splitPartnerId, the split-pair marker) isn't reflected indumpTree, so it can only be checked by pixel-grabbing.Fix: expose
splitPartnerId(and similar overlay-derived state) in aget pan/get slicesnapshot so split-pairing etc. is assertable without image diffing. (Surfaced in #3794.)Priority
#1 is the only correctness item (a real, if fail-safe, TX-guard false-positive) and is the most worth doing. #2–#5 are drivability/observability conveniences that would let future feature PRs prove themselves headlessly without per-PR workarounds.
Refs #3646, #3819, #3826. cc @jensenpat (bridge author).