Feasibility spike: keep buzz-agent's ACP wire contract exactly as-is, but
replace the hand-written agent loop with goose used as a Rust library.
13,259 -> 1,562 src LOC (88% cut), plus ~5,800 test LOC that covered the
deleted loop.
Deleted, now goose's:
llm.rs 3846 -> goose::providers (superset of the 4 providers)
mcp.rs 1139 -> goose::agents::extension_manager
auth.rs 845 -> goose::providers (incl. Databricks OAuth)
hints.rs 726 -> prompt_manager::with_hints
catalog.rs 631 -> goose::providers::init
builtin.rs 575 -> goose skills platform extension
handoff.rs 430 -> goose::context_mgmt (auto-compaction)
Kept deliberately (the contract buzz-acp depends on):
wire.rs 293 verbatim; agentInfo.name = "buzz-agent" (kind-44200 harness
attribution); 6-method surface; activeRunId with _meta nested inside
update; usage_update before the session/prompt response; keepalive
ticker; error -> JSON-RPC code mapping; single-flight; size caps.
This is NOT "goose as the harness". Picking Goose from the harness gallery
still shells out to a user-installed goose CLI. This is buzz-agent's own
identity with a goose-powered loop.
Why a separate crate excluded from the workspace: crates/buzz-agent is a
library linked into sprig AND desktop/src-tauri, so goose's ~700-crate graph
would land in the Tauri build and the workspace lockfile. Own Cargo.lock,
same isolation trick as PR #1526.
Notable: driving the library is what makes the persona work at all. Goose's
own ACP server never reads systemPrompt (zero hits in goose/crates/goose/src)
and both PRs that would have wired it -- buzz#1290, goose#9971 -- are closed
unmerged. tests/stdio_turn.rs asserts Fizz's prompt reaches the provider.
Also: GOOSE_MODE is left at goose's default rather than forced to "auto"
(auto-approve every tool call), which is what the desktop catalog ships for
the external goose runtime.
Signed-off-by: Michael Neale <michael.neale@gmail.com>