Mari's re-review: after a rollback/reconciliation pass, a failed
stopAgent leaves a process running under the wrong scope and a failed
startAgent leaves it stopped — committing a normal UI scope in either
case claims a convergence that does not exist. All process rollbacks
are still attempted, but any failure now surfaces onUnrecoverable
(card disables the toggle) instead of setUi.
Tests: the one-rollback-restart-fails case now asserts hard recovery
and no UI claim; new rollback-stop-failure case asserts the same.
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Two review findings from the PR #1981 session-scope setting:
Legacy materialization (Mari, MAJOR 1): hydration read the legacy
acp_top_level_sessions override but never persisted the translation, so
removing the compatibility reader would silently flip explicit channel
users to the thread default. hydrate_scope now atomically materializes
an explicit legacy value into acp_session_scope during hydration —
false→channel, true→thread — while the bare no-field default stays
unwritten (unset remains distinguishable from an override) and an
explicit new-field value is never rewritten. DesktopSettings gains a
#[serde(flatten)] passthrough so any save preserves JSON fields owned
by other features. A failed materialization write keeps the translated
scope in memory and the legacy field on disk for retry — no divergence.
Rollback convergence (Mari, MAJOR 2): on apply failure with a failed
rollback write, the old path restarted processes and forced the UI to
'previous' while the authoritative backend still held the new value —
false convergence. applyAcpSessionScopeSetting now establishes the
authoritative scope first (confirmed rollback write, else re-read via
getBackend), reconciles processes and UI to that actual value, and if
the authority is unreadable fires onUnrecoverable — the card surfaces a
hard recovery state and disables the toggle instead of claiming a scope.
Tests: 7 new Tauri hydration/materialization tests (incl. read-only-dir
write-failure injection) and 2 new rollback-matrix tests (authority
re-read reconciliation; double-failure hard recovery).
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Three fixes for PR CI:
- fmt: apply rustfmt to the rebased command_env helper in
managed_agents/runtime/tests.rs (Rust Lint failure).
- lib.rs over the 1000-line limit: move the window/haptic tauri
commands (perform_sidebar_default_haptic, title_bar_double_click,
fill_window, toggle_maximize) into commands/window_actions.rs where
they belong with the other frontend-forwarded commands
(1012 -> 901 lines, back under the default limit).
- app_state.rs over its ratchet: drop the AppState field for the
experiment entirely. The experiment flag now lives in
commands/experiments.rs as a process-local atomic, lazily hydrated
from the Rust-owned store on first read. The hydrate-before-restore
ordering invariant now holds by construction (the spawn boundary is
the first reader) instead of by an app-setup ordering requirement,
and app_state.rs is byte-identical to main — one less shared surface
the experiment touches.
desktop src-tauri: cargo test 1483 passed, clippy and fmt clean, and
node scripts/check-file-sizes.mjs passes.
Co-authored-by: npub1zurdm6fx3kksz8f8d8y4js3mvjyu3rshlpqejr8wa8hta5tsqqeshmes7w <1706dde9268dad011d2769c959423b6489c88e17f841990ceee9eebed1700033@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1zurdm6fx3kksz8f8d8y4js3mvjyu3rshlpqejr8wa8hta5tsqqeshmes7w <1706dde9268dad011d2769c959423b6489c88e17f841990ceee9eebed1700033@sprout-oss.stage.blox.sqprod.co>
Reduce the ongoing cost of the top-level-sessions experiment by
collapsing its scattered maintenance surfaces without changing behavior:
- pool: replace eager session_owners reconciliation (5 lifecycle call
sites + retains in return_agent / invalidate_channel_sessions /
model-switch paths) with a single lazy prune_session_owners() at the
one read site in try_claim. Future slot-lifecycle paths can no longer
forget the purge; the invariant converges at one choke point.
- queue: extract pop_cancelled() / dispatch_cancelled() helpers so the
three copy-pasted cancelled-batch blocks in flush_next become
one-liners.
- session key: drop the top_level_sessions bool param and dead
thread-tag fallback from conversation_session_key; remove the
redundant PromptContext.top_level_sessions field. The key is now
purely data-driven from batch.conversation_root, which is only
populated at queue-push when the experiment is enabled.
Net -59 lines. cargo test -p buzz-acp: 530 passed; clippy and fmt
clean. Disabled-mode paths degenerate identically (root=None
everywhere).
Co-authored-by: npub1zurdm6fx3kksz8f8d8y4js3mvjyu3rshlpqejr8wa8hta5tsqqeshmes7w <1706dde9268dad011d2769c959423b6489c88e17f841990ceee9eebed1700033@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1zurdm6fx3kksz8f8d8y4js3mvjyu3rshlpqejr8wa8hta5tsqqeshmes7w <1706dde9268dad011d2769c959423b6489c88e17f841990ceee9eebed1700033@sprout-oss.stage.blox.sqprod.co>
## Why
On macOS, GUI apps launched from Finder/Spotlight/Dock inherit a minimal PATH from launchd (`/usr/bin:/bin:/usr/sbin:/sbin`). The `discover_provider_candidates()` function in `backend.rs` only scanned this process PATH when looking for `buzz-backend-*` executables. As a result, backend providers (like `buzz-backend-blox`) were never found, and the "Run on" dropdown in Agent Settings was hidden — even though the binary existed both in the app bundle (`Contents/MacOS/`) and in `~/.local/bin`.
## What
Augment the search directories in `discover_provider_candidates()` with:
1. **exe parent dir** (`Contents/MacOS/` in a `.app` bundle) — so bundled providers are always found regardless of how the desktop was launched
2. **`~/.local/bin`** — the conventional location for user-installed provider binaries (symlinks created by install scripts)
Both directories are only added if not already present in PATH (deduplication). The exe parent dir is prepended (highest priority for bundled providers); `~/.local/bin` is appended.
## Verification
- `cargo check --lib` passes
- All 17 `managed_agents::backend` unit tests pass
- Pre-push hook `desktop-tauri-test` passes (38s)
## References
Root cause confirmed by inspecting the running `buzz-desktop` process environment:
```
$ ps eww <pid> | grep PATH
PATH=/usr/bin:/bin:/usr/sbin:/sbin
```
---
Generated with Fizz