mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
refactor: move agent Git bootstrap into ACP harness (#7819)
discovered in https://github.com/block/buzz/issues/7742#issuecomment-5783512985 ## Summary Goose uses its native shell, so it bypassed the Git identity and signing setup inside `buzz-dev-mcp`. Agent commits could use the host Git identity, while MCP shells had a separate config. This moves Git setup into `buzz-acp`, where both paths receive the same agent identity, Nostr signer, and relay-scoped credential helper. Before: ```text Buzz Desktop └─ buzz-acp ← Desktop supplied relay Git authentication ├─ Goose → native shell ← no agent Git author or signing setup └─ Buzz Agent └─ buzz-dev-mcp └─ shell ← MCP created the keyfile and Git signing config ``` After: ```text Buzz Desktop or Sprig └─ buzz-acp ← owns the keyfile, identity, signing, and scoped credentials ├─ Goose → native shell ← inherits the complete Git environment └─ Buzz Agent └─ buzz-dev-mcp └─ shell ← receives the same Git environment via mcpServers[].env ``` The harness keeps the signing key in a private temporary file and removes it on normal exit, startup failure, and graceful termination. It composes inherited `GIT_CONFIG_*` entries, forwards the complete block to MCP servers, and bundles the helpers through the ACP multicall entrypoint. For standard `buzz-acp` launches, Desktop and Sprig no longer write Git config. A custom Desktop ACP command bypasses the harness, so Desktop preserves its prior relay-scoped credential helper for that supported override. This changes Git settings for every ACP runtime. The startup signal path also changes so a termination during adapter initialization removes the keyfile. The temporary file can remain after SIGKILL or a machine crash. ### Related issue Related: #6177 covers stricter commit identity enforcement and touches the same Git paths. That PR and this one need to be reconciled before either lands. No issue was found for this runtime bootstrap gap. ### Testing - Ran the ignored `git_runtime_tests` with real Goose 1.50.0 and Buzz Agent ACP sessions. `real_goose_native_git_shell` passed again on this PR branch with `BUZZ_TEST_BIN_DIR` pointing to built binaries. Goose made a signed commit and tag through its native shell; Buzz Agent did the same through its MCP shell. Both verified signatures, identity, credential scoping, and keyfile cleanup. - Built the Linux Sprig image and ran `scripts/test-sprig-image.sh buzz-sprig:acp-git-bootstrap`. The container made and verified a signed commit and tag, then confirmed keyfile removal after SIGTERM. - `just ci` passed on the original branch. After rebasing onto `main` and addressing review feedback, the ACP Git bootstrap integration tests, focused desktop smoke test, custom-command regression test, formatting, and ACP/Desktop Clippy passed. The pre-push hook hit two timing-sensitive ACP deadline tests under parallel load; both passed alone and the complete ACP package passed serially (964 library, 2 Git bootstrap, 9 pool lifecycle tests). The push used `--no-verify` after those checks; GitHub CI is rerunning on the new head. - Under injected `BUZZ_ACP_ALLOWED_RESPOND_TO`, `BUZZ_ACP_LAZY_POOL`, and `BUZZ_ACP_IDLE_POOL_SLEEP`, the clean-env serial package command in `crates/buzz-acp/TESTING.md` passed: 964 active library tests, 2 Git bootstrap tests, and 9 pool lifecycle tests. Both named Databricks OAuth tests passed locally; another reviewer reproduced their environment-specific failures on `main`. - No authenticated relay clone or push was run. The local probes used disposable repositories and did not contact a relay. Generated with Codex --------- Signed-off-by: Salman Mohammed <smohammed@squareup.com>
This commit is contained in:
@@ -3,10 +3,10 @@
|
||||
# harness, agent, and developer MCP. The archive exposes these command names:
|
||||
#
|
||||
# sprig implementation binary
|
||||
# buzz-acp link to sprig (ACP harness)
|
||||
# buzz-acp link to sprig (ACP harness and Git helper personalities)
|
||||
# buzz-agent link to sprig (ACP-compliant agent)
|
||||
# buzz-dev-mcp link to sprig (developer MCP server; also dispatches
|
||||
# rg/tree/buzz/git-credential-nostr/git-sign-nostr)
|
||||
# rg/tree/buzz)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/build-sprig.sh [version] [target]
|
||||
@@ -140,12 +140,12 @@ to one multicall binary so shared Rust runtime/TLS code is stored only once.
|
||||
Commands:
|
||||
|
||||
- `sprig` — prints usage/version. Invoke a personality by one of the links below.
|
||||
- `buzz-acp` — ACP harness that bridges Buzz channel events to an
|
||||
- `buzz-acp` — ACP harness and `git-credential-nostr` / `git-sign-nostr`
|
||||
multicall entrypoint that bridges Buzz channel events to an
|
||||
ACP-compliant agent over stdio.
|
||||
- `buzz-agent` — ACP-compliant agent (spawns MCP servers, calls LLMs).
|
||||
- `buzz-dev-mcp` — Developer MCP server (shell, str_replace, todo) and
|
||||
multicall entrypoint for `rg`, `tree`, `buzz`, `git-credential-nostr`,
|
||||
`git-sign-nostr`.
|
||||
multicall entrypoint for `rg`, `tree`, and `buzz`.
|
||||
|
||||
See `sprig.json` for SHA-256s, sizes, target, and source git SHA.
|
||||
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Match desktop's URL-scoped git credential configuration without installing a
|
||||
# helper globally (which would make it answer for unrelated remotes).
|
||||
if [[ -n "${BUZZ_RELAY_URL:-}" ]]; then
|
||||
relay_http_url="${BUZZ_RELAY_URL/#ws:/http:}"
|
||||
relay_http_url="${relay_http_url/#wss:/https:}"
|
||||
relay_http_url="${relay_http_url%/}"
|
||||
git config --global "credential.${relay_http_url}/git.helper" \
|
||||
/usr/local/bin/git-credential-nostr
|
||||
git config --global "credential.${relay_http_url}/git.useHttpPath" true
|
||||
fi
|
||||
|
||||
# buzz-acp owns ephemeral Git setup for both native and MCP shells.
|
||||
# The harness must receive Kubernetes' termination signal directly.
|
||||
exec buzz-acp "$@"
|
||||
|
||||
@@ -16,28 +16,85 @@ assert_run '
|
||||
for name in buzz-agent buzz-dev-mcp rg tree buzz git-credential-nostr git-sign-nostr; do
|
||||
test "$(readlink "/usr/local/bin/$name")" = sprig
|
||||
done
|
||||
test "$(git config --system gpg.x509.program)" = /usr/local/bin/git-sign-nostr
|
||||
! git config --system --get gpg.x509.program
|
||||
! git config --system --get-all credential.helper
|
||||
test "$HOME" = /home/agent
|
||||
test "$(pwd)" = /home/agent
|
||||
'
|
||||
|
||||
assert_run '
|
||||
grep -Eq "^[[:space:]]*exec buzz-acp" /usr/local/bin/sprig-entrypoint
|
||||
! grep -Eq "^[[:space:]]*(buzz-acp|bash -c .*buzz-acp)" /usr/local/bin/sprig-entrypoint
|
||||
'
|
||||
|
||||
docker run --rm --entrypoint /bin/bash \
|
||||
-e BUZZ_RELAY_URL=wss://relay.example.test/ "$IMAGE" -ceu '
|
||||
/usr/local/bin/sprig-entrypoint --help >/dev/null 2>&1 & pid=$!
|
||||
for _ in 1 2 3 4 5; do
|
||||
git config --global --get credential.https://relay.example.test/git.helper >/dev/null 2>&1 && break
|
||||
sleep 0.1
|
||||
done
|
||||
test "$(git config --global --get credential.https://relay.example.test/git.helper)" = /usr/local/bin/git-credential-nostr
|
||||
test "$(git config --global --get credential.https://relay.example.test/git.useHttpPath)" = true
|
||||
/usr/local/bin/sprig-entrypoint --help >/dev/null
|
||||
! git config --global --get credential.https://relay.example.test/git.helper
|
||||
! git config --global --get-all credential.helper
|
||||
wait "$pid" || true
|
||||
'
|
||||
|
||||
# Exercise the image entrypoint, ACP harness, and both Git helper personalities
|
||||
# without contacting a relay.
|
||||
docker run --rm -i --entrypoint /bin/bash "$IMAGE" -seuo pipefail <<'SCRIPT'
|
||||
probe_dir=$(mktemp -d)
|
||||
trap 'rm -rf "$probe_dir"' EXIT
|
||||
export PROBE_DIR="$probe_dir"
|
||||
cat > "$probe_dir/adapter" <<'ADAPTER'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
cd "$PROBE_DIR"
|
||||
git init -q repo
|
||||
cd repo
|
||||
git -c core.hooksPath=/dev/null commit -s --allow-empty -qm probe
|
||||
git tag -m probe probe
|
||||
git verify-commit HEAD
|
||||
git verify-tag probe
|
||||
test "$(git show -s --format=%an HEAD)" = "$(git config user.name)"
|
||||
test "$(git show -s --format=%cn HEAD)" = "$(git config user.name)"
|
||||
git config nostr.keyfile > ../keyfile
|
||||
test "$(git config --get-urlmatch credential.helper https://relay.invalid/git/repo)" = nostr
|
||||
! git config --get-urlmatch credential.helper https://unrelated.invalid/git/repo
|
||||
printf 'capability[]=authtype\nprotocol=https\nhost=relay.invalid\npath=git/repo\nwwwauth[]=Nostr method="GET"\n\n' |
|
||||
git credential fill > ../credential-result
|
||||
grep -q '^authtype=Nostr$' ../credential-result
|
||||
printf done > ../done
|
||||
exec sleep 30
|
||||
ADAPTER
|
||||
chmod 700 "$probe_dir/adapter"
|
||||
# Disposable test key; never used with any relay.
|
||||
GIT_AUTHOR_NAME='Inherited Human' GIT_AUTHOR_EMAIL=human@example.invalid \
|
||||
GIT_COMMITTER_NAME='Inherited Human' GIT_COMMITTER_EMAIL=human@example.invalid \
|
||||
BUZZ_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000001 \
|
||||
BUZZ_RELAY_URL=wss://relay.invalid \
|
||||
BUZZ_ACP_AGENT_COMMAND="$probe_dir/adapter" BUZZ_ACP_AGENT_ARGS= \
|
||||
/usr/local/bin/sprig-entrypoint > "$probe_dir/log" 2>&1 &
|
||||
pid=$!
|
||||
for _ in {1..100}; do
|
||||
[[ -f "$probe_dir/done" ]] && break
|
||||
sleep 0.1
|
||||
done
|
||||
if ! kill -TERM "$pid" 2>/dev/null; then
|
||||
wait "$pid" || true
|
||||
cat "$probe_dir/log"
|
||||
echo "harness exited before SIGTERM" >&2
|
||||
exit 1
|
||||
fi
|
||||
for _ in {1..50}; do
|
||||
kill -0 "$pid" 2>/dev/null || break
|
||||
sleep 0.1
|
||||
done
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill -KILL "$pid"
|
||||
wait "$pid" || true
|
||||
cat "$probe_dir/log"
|
||||
exit 1
|
||||
fi
|
||||
if ! wait "$pid"; then
|
||||
cat "$probe_dir/log"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$probe_dir/done" ]]; then
|
||||
cat "$probe_dir/log"
|
||||
exit 1
|
||||
fi
|
||||
keyfile=$(cat "$probe_dir/keyfile")
|
||||
test ! -e "$keyfile"
|
||||
SCRIPT
|
||||
|
||||
echo "PASS: Sprig image runtime contract ($IMAGE)"
|
||||
|
||||
Reference in New Issue
Block a user