## Summary
- split the managed-agent runtime warehouse into cohesive modules for
process ownership/termination, orphan sweeping, dead-instance reaping,
lifecycle synchronization, and runtime metadata
- preserve the existing `runtime` API through narrow re-exports; helper
bodies and platform `cfg` branches are unchanged apart from
module-qualified visibility
- reduce `runtime.rs` from 2,220 lines on `main` to 908 lines and remove
its temporary file-size override, restoring the standard 1,000-line
ceiling
## Why
`main` failed after stale successful PR checks allowed independent
growth to combine above `runtime.rs`'s 2,216-line override. The earlier
fix in #2974 extracted only 55 lines and left the monolith on a special
ratchet. This replacement includes that extraction but establishes
responsibility boundaries and removes the exception entirely.
## Module boundaries
- `process.rs` — process identity, ownership markers, receipt
validation, and termination primitives
- `orphan_sweep.rs` — same-instance orphan discovery and cleanup
- `instance_reaper.rs` — foreign/dead desktop instance detection and
agent reaping
- `lifecycle.rs` — tracked runtime synchronization and stale record
cleanup
- `metadata.rs` — model/provider metadata resolution
- `runtime.rs` — summary/config/spawn orchestration and composition
## Validation
At `a824fda31eff6ecc0d39ca1b8ea5602a108897e6`:
- pre-push `desktop-check`
- pre-push `desktop-test`
- pre-push full `desktop-tauri-test`: 1,637 passed, 0 failed, 14
ignored; integration + doc tests passed
- `cargo check --manifest-path desktop/src-tauri/Cargo.toml --lib`
- `cargo fmt --manifest-path desktop/src-tauri/Cargo.toml --all --
--check`
- `node desktop/scripts/check-file-sizes.mjs`
Supersedes #2974 and #2930.
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Princess Donut <68157ebd23b3897c1991015c3038658ea916200c67d3a54620b0754d1b92f6e0@buzz.block.builderlab.xyz>
Two follow-ups from review at 4fcd5f138:
1. RuntimeLogo keyed on PRESET_LOGOS[id], so Cursor — a preset with a
deliberately unbundled logo (licensing, enforced by
FALLBACK_ONLY_PRESETS) — fell through to ProfileAvatar initials while
the gallery below showed RuntimeIcon's terminal glyph. Key on
runtime.source === "preset" instead: every preset now routes through
RuntimeIcon and both surfaces agree. Playwright regression added
(Cursor row renders the glyph svg, never an img or initials).
2. Windows CI red root-caused: the spawn_hash I2 tests call
warm_harness_registry_from_dir without registry_test_lock, so a
parallel re-warm between the two hash computations makes both resolve
to no-definition (h1 == h2). Reproduced on macOS under
--test-threads=16; the same parallel runs surfaced two sibling flakes
of the same global-state class, both from this PR's new tests:
- discover_acp_runtimes_from auth probes warm the process-global
login-shell PATH cache without lock_path_mutex, poisoning
refresh_login_shell_path_clears_cache while managed_path_resolution
had HOME/PATH swapped to a tempdir.
- grandchild_inherits_pgid spawned sh via PATH lookup and hit
NotFound during another test's PATH-swap window.
Fix: registry_test_lock on the 3 spawn_hash tests + the 2
definition_env discovery tests; lock_path_mutex (path lock first,
then registry — order documented) on the 4 discovery tests driving
discover_acp_runtimes_from; absolute /bin/sh in the PGID test.
Test-only; 8 consecutive parallel suite runs green after the fix
(3 distinct failures in 11 runs before).
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Dawn's blocker: the loader-boundary collision/dedup enforcement was
untested — deleting either block left the full suite green. The stale
load_applies_id_collision_check only called check_id_collision directly
and its comment described the pre-fix architecture. Replaced with a
version that drives the REAL load_custom_harnesses against a shadowing
goose.json, plus a dedup twin (two files, same id -> len()==1). Both
verified to kill the mutants locally.
Wren's test-quality gap: the interleaving regressions pinned the
warm_harness_registry_locked seam but never executed discovery — a
stale-publish mutant of discover_acp_runtimes_from stayed green. Added
a cfg(test) pre_publish_test_hook between discovery's scan and its
registry publish, and two production-path regressions that land a
save/delete through the real discover_acp_runtimes_from call. Verified
both red under the stale-publish mutant.
Wren's product gap: the delete confirmation could be confirmed before
the blast-radius queries settled (pending queries rendered as zero
dependents with an enabled destructive button). New deleteConfirmState
drives the confirm UI: disabled + 'Checking which agents…' while
either query is initial-loading; on query failure deletion stays
possible but the copy says the count is unknown instead of claiming
zero. Unit-tested for pending/error/settled states.
Dawn + Wren both: get_agent_models now routes harness-resolution
errors through user_facing_harness_error (model_discovery_error
helper), so a dangling harness renders as a sentence, never the raw
DANGLING_HARNESS_ID sentinel. Also added Dawn's requested comment at
discovery's publish noting which tests pin the seam.
File-size ratchets bumped with documented deltas (all test/test-seam
growth).
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Conflicts resolved in agent_models.rs / agent_models_tests.rs: main's #2890
(live Databricks discovery via effective_discovery_provider +
provider_env_var) composed with this branch's unified
resolve_effective_harness_descriptor. get_agent_models now passes the
record's saved provider plus the runtime's provider_env_var (from
known_acp_runtime on the descriptor command) into
effective_discovery_provider, replacing both main's
SavedAgentModelDiscoveryConfig snapshot and this branch's ad-hoc
BUZZ_AGENT_PROVIDER env read.
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Refs #2062
This carries forward the relay-mesh recovery work from #2304 by @Bartok9
(cherry-picked with original authorship/sign-offs) and adds the
startup/readiness supervision and packaging fixes found while validating
it against a real two-machine Buzz setup.
## From #2304
- Watch the local OpenAI ingress (`:9337`) after launch and re-arm a
stale relay-mesh runtime.
- Require consecutive failed probes before eviction so a transient
inference stall does not cause a cold restart.
- Bound stale-runtime shutdown, preserve runtime identity across the
asynchronous probe, and never evict a concurrent replacement.
- Re-arm only for agents that are actually running; deliberately stopped
agents stay stopped.
- Persist an actionable sentinel error under the managed-agent store
lock and clear only that error after recovery.
- Treat serve-to-client fallback as an intentional fail-safe; configured
serve restoration remains on its existing path.
## Added here
- Use the inference ingress (`:9337`), rather than management port
`:3131`, as Buzz's client-readiness boundary. A usable client no longer
fails or holds agent-save open merely because management startup is
still pending.
- Supervise the embedded SDK startup asynchronously, publish a pending
status while management is unavailable, and keep its mesh identity
alive.
- Avoid racing a replacement while SDK startup still owns the embedded
runtime. If that pending startup later loses ingress while a running
agent still needs it, request a controlled Buzz restart to reclaim the
otherwise-unreachable SDK thread.
- Defer roster-driven replacement while client management startup is
pending.
- Keep post-launch recovery in a dedicated module so the mesh entry
point remains within the desktop file-size gate.
- Explicitly mark generated Unix sidecars executable. On macOS, copying
over an existing non-executable destination preserved its old mode,
causing packaged `buzz-acp`, `buzz-agent`, and tool sidecars to be
reported as missing.
## Validation
Automated:
- `just ci` — passed, including formatting, Clippy with warnings denied,
desktop/web/mobile checks and tests, and builds.
- Full Tauri mesh-feature suite — 1,702 passed, 0 failed, 15 ignored.
- Mesh-feature Clippy with `-D warnings` — passed.
- Release macOS app bundle with `mesh-llm` — built successfully; every
bundled sidecar passed executable-mode and deep code-signature
verification.
Live two-machine E2E:
- M5: released Buzz serving `unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M`.
- Mac mini: this branch's packaged Buzz running a saved
`buzz-agent`/relay-mesh agent.
- Confirmed `:9337` accepted inference and the saved ACP harness started
with no error while `:3131` was still unavailable.
- Exact inference succeeded before restart (`CORRECTED-MINI-E2E-OK`).
- Bespoke Buzz shut down cleanly in 2.3s, then restored ingress and the
saved harness in 18.8s while `:3131` was still unavailable.
- Exact inference succeeded after restart (`AFTER-RESTART-E2E-OK`).
- A real Buzz `@C55` message traversed desktop → `buzz-acp` →
`buzz-agent` → mini `:9337` → M5 compute and published the requested
reply successfully.
---------
Signed-off-by: Bartok9 <danielrpike9@gmail.com>
Signed-off-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Bartok9 <danielrpike9@gmail.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
Brings the branch up to date with origin/main (2a051a404) so CI and local
gates run against the tree that will actually merge. Requested as a merge
commit rather than a rebase to keep Duncan's authored history intact.
Two ratchet entries in desktop/scripts/check-file-sizes.mjs needed
composing, since both sides raised per-file ceilings from a shared base:
- src-tauri/src/commands/agent_discovery.rs — textual conflict. BYOH took
1826 -> 2038 (+212); main #2767 took 1826 -> 1836 (+10). Resolved to
2048 with both comment blocks kept, preserving the slack each side
intended rather than discarding one growth.
- src-tauri/src/managed_agents/discovery.rs — no textual conflict, but the
BYOH ceiling of 1715 predates main's +17 and the merged file is 1729
lines, so the check failed on a clean auto-merge. Composed to 1732.
The overrides map is a ceiling (violation only when lineCount > limit), so
composing deltas is the resolution that matches the file's convention.
Verified on the merged tree: desktop file-size check clean, frontend suite
3554/3555 (the one failure is the pre-existing styled-qr-code 'Cannot find
package qrcode' local module-resolution fault, which fails identically on
pristine heads), presetLogos drift guard 10/10 with all 8 preset ids still
parsing out of main's modified discovery.rs, tsc --noEmit clean, biome
clean over 1640 files, just test-unit 5/5 crates, and desktop-tauri-test
1691/1691.
Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
## Why
The Codex adapter install-plan test depended on the process-global
login-shell PATH cache, making it flaky under concurrent or loaded CI
runs.
## What
- Thread an explicit probe PATH through adapter install planning
- Use a controlled PATH in Codex install-plan tests
- Update the existing desktop file-size allowance for the focused seam
## Risk Assessment
Low — production behavior keeps using the same augmented PATH; only
dependency injection and deterministic tests change.
## References
- Failure:
https://github.com/block/buzz/actions/runs/30110680608/job/89539202266
- Validation: `just desktop-tauri-test`; `cd desktop && pnpm check`;
full pre-push hooks
Generated with Codex
---------
Signed-off-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz>
Co-authored-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz>
Co-authored-by: Codex <noreply@openai.com>
D-12: Revert mobile/pubspec.lock to origin/main. The meta 1.17→1.18 /
test 1.30→1.31 churn was a no-source-change lockfile bump introduced by
accident; reverting eliminates the unrelated diff.
D-15: Add OpenClaw execution-locus note to the preset's install_hint.
Eva's finding: openclaw acp executes tools inside the Gateway daemon, not
in the Desktop process. Desktop-injected BUZZ_* env vars reach the
openclaw harness process itself but do NOT automatically propagate to
the Gateway's execution environment. The install_hint now surfaces this
caveat so users who need BUZZ_* credentials at execution time know they
must set them on the Gateway's own environment.
F8 (onboarding navigate test): New pure-logic test file
postOnboardingNav.test.mjs proves the App.tsx postOnboardingNav
useEffect predicate — navigateAfterComplete does not fire before
machine.stage reaches 'ready', fires exactly once on the ready
transition, is cleared after firing (no double-fire), fires immediately
if nav arrives while already ready, and carries the exact
{to: '/settings', search: {section: 'agents'}} shape from
MachineOnboardingFlow's navigateToAgentSettings action.
C-10 (e2eBridge + handler tests): Extract save_custom_harness /
delete_custom_harness handler logic into e2eBridgeCustomHarnesses.ts
(exported module-level functions + mockCustomHarnesses Map +
resetMockCustomHarnesses). Wire the handlers into e2eBridge.ts:
- mockCustomHarnesses imported and appended to discover_acp_providers
results so saved custom harnesses appear in future discovery calls
- case 'save_custom_harness' → handleSaveCustomHarness
- case 'delete_custom_harness' → handleDeleteCustomHarness
New test file e2eBridgeCustomHarnesses.test.mjs (14 tests across 3
describe groups) proves: save → store, non-empty env preserved,
empty env absent, same-ID edit replaces, rename removes old + inserts
new, delete removes, delete idempotent, Map reference is shared.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
B-4 (persistence contract): Replace the two simulated round-trip tests that
called raw fs::write/remove_file with six tests that exercise the real
save_custom_harness_to_dir helper directly:
- save_to_dir_create_writes_file_and_loads_back
- save_to_dir_same_id_edit_replaces_content
- save_to_dir_backup_is_cleaned_up_after_same_id_edit
- save_to_dir_rename_removes_old_file_and_creates_new
- save_to_dir_rename_nonexistent_old_id_is_non_fatal
- save_to_dir_roundtrip_with_env_preserves_values
B-3 (env validation boundary): Six tests exercising validate_harness_definition_pub
integration with validate_user_env_keys for the documented attack surfaces:
- validate_rejects_malformed_key_with_equals_sign (BUZZ_AUTH_TAG=x forgery shape)
- validate_rejects_reserved_key_buzz_managed_agent (ownership marker)
- validate_rejects_reserved_key_case_insensitive (lowercase bypass)
- validate_rejects_nul_byte_in_value (Command::env panic protection)
- validate_rejects_value_over_per_value_size_limit
- validate_accepts_well_formed_env
B-2 (API boundary): Export fromRawAcpRuntimeCatalogEntry from tauri.ts and
add four tests to tauri.test.mjs proving the Rust definition_env snake_case
field is mapped to definitionEnv camelCase, that absent definition_env defaults
to {} (not undefined), and that env round-trips end-to-end through the mapper
so a save-then-edit cycle cannot erase definition env.
B-6 (concurrent-safe registry): Add save_and_warm + delete_and_warm functions
in custom_harnesses.rs that hold a PERSIST_MUTEX for the filesystem mutation
and the subsequent warm_harness_registry_from_dir call as an atomic unit.
Update save_custom_harness and delete_custom_harness Tauri commands to use
these helpers. Eliminates the lost-update window where two concurrent saves
could interleave their warm calls and produce a stale registry snapshot.
File-size override added for custom_harnesses.rs (1042 lines after the new
tests; queued to split once the feature stabilizes).
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
## Why
Installing the Codex, Claude, or Goose desktop app does not install the
command-line harness Buzz needs. The current UI makes that distinction
unclear, links some missing-CLI states to adapter documentation, and can
report a successful install from the installer exit code even when
runtime discovery still fails. On Windows, Buzz also invokes Goose's
Bash installer, which writes the executable somewhere Buzz does not
discover.
## What
- distinguish missing vendor CLIs from missing or outdated ACP adapters
in runtime metadata and UI guidance
- link Codex, Claude Code, and Goose missing-CLI states to their
official CLI installation documentation
- explain in Settings, onboarding, and agent configuration that the
desktop app alone is not sufficient
- use Goose's official PowerShell installer on Windows
- refresh PATH and rediscover the requested runtime after installation,
keeping the control retryable if the runtime is still unavailable
- add Rust and Playwright regression coverage for Windows installer
selection, CLI/adapter guidance, false-success prevention, verified
installs, and onboarding copy
## Risk Assessment
Medium. This changes desktop onboarding and runtime installation
behavior. Successful installs now require the runtime catalog to verify
availability; previously hidden discovery failures will surface as
actionable errors instead of a false success state.
## References
- [Codex CLI installation](https://developers.openai.com/codex/cli/)
- [Claude Code
installation](https://code.claude.com/docs/en/getting-started)
- [Goose
installation](https://goose-docs.ai/docs/getting-started/installation/)
- Follow-up to #2563 and #2587
## Validation
- `just desktop-typecheck`
- `just desktop-test` — 3,455 passed
- focused Rust post-install verification tests
- focused Playwright Doctor/onboarding coverage (in progress; CI and
local sequential rerun will provide final results)
Generated with Codex
---------
Signed-off-by: Atish Patel <atish@squareup.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Goose <opensource@block.xyz>
## Problem
On Windows, `install_shell_command` wraps every install command in Git
Bash `-l -c`, including the Windows-specific `powershell.exe … irm
https://chatgpt.com/codex/install.ps1 | iex` command. A Git Bash login
shell prepends its POSIX dirs (`C:\Program Files\Git\usr\bin`) to PATH,
so when Codex's `install.ps1` shells out to bare `tar -xzf C:\…`, it
resolves Git's GNU tar (`/usr/bin/tar`) instead of Windows bundled
bsdtar. GNU tar parses `C:` as a remote host:
```
tar (child): Cannot connect to C: resolve failed
gzip: stdin: unexpected end of file
/usr/bin/tar: Child returned status 128
/usr/bin/tar: Error is not recoverable: exiting now
Downloaded Codex package archive did not contain the expected package layout.
```
Claude's installer doesn't hit the same failure because it doesn't shell
out to `tar`.
## Solution
On Windows, detect `powershell.exe` install commands and spawn them
natively (`Command::new("powershell.exe")`) instead of routing them
through Git Bash. The discriminator is a case-insensitive prefix check
on the first whitespace-delimited token — minimal and precise.
The native spawn preserves everything `install_shell_command` provides
that applies:
- `NPM_CONFIG_*` / `COREPACK` env strip + managed npm prefix env
- PATH composed from managed Buzz dirs + inherited process PATH (no
POSIX login-shell dirs)
- `CREATE_NO_WINDOW` so no console flash
- stdin null, piped-drain in `run_install_command`
- The retry/backoff/annotate logic is fully shared
The `-Command` body is split correctly at the boundary
(case-insensitive) and passed as a single argument to preserve pipes and
spaces inside the installer script call.
Non-PowerShell commands (e.g. `npm install -g …` adapter steps) continue
through the existing Git Bash path unchanged.
## Tests
6 unit tests:
1. `is_powershell_command` detection (positive + negative)
2. Routing: PowerShell → native spawn on Windows, non-PowerShell → Git
Bash
3. Unix: non-Windows path returns the shell command unchanged
(compile-time cfg)
4. `-Command` body preservation (no bash args in native spawn; body is
single arg)
Full `just desktop-tauri-test` suite: 1627/1627 passing. Windows CI will
validate end-to-end.
---------
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>