mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
## Why Early relay failures can currently appear as a container restart without a trustworthy in-process account of whether crypto, structured logging, configuration, relay identity, or the metrics listener failed. Most of those steps happen before the Prometheus exporter exists, so their chronology belongs in logs rather than metrics. Implements the logs-only early-startup slice of #7238. Post-bind Prometheus exporter supervision is tracked separately in #7284. ## What changed - create a process lifecycle recorder before the Tokio runtime and emit a fixed, versioned JSON schema directly to stderr; - record started and exactly one terminal event for `crypto_init`, `tracing_init`, `config_load`, `key_load`, `metrics_bind`, and the aggregate `process_telemetry` phase; - keep every status and reason bounded and suppress raw errors that could contain credentials, keys, URLs, or other secrets; - return typed metrics-install errors so `metrics_bind` can be classified without logging raw values, while preserving the existing public `metrics::install` API; - document the logs-only evidence contract and add real child-process regressions for success and failure paths. This PR adds **no startup metric families** and no dashboard contract. Existing application metrics remain unchanged. ## Verification Exact head: `8faf7526822a119efa035e58b2b3c59aa67fc81d` - `cargo fmt --all -- --check` - `cargo clippy -p buzz-relay --all-targets -- -D warnings` - relay binary target: 13 passed, 1 PostgreSQL-only test ignored - real relay child-process lifecycle target: 9 passed - full relay package library target: 1,023 passed, 89 ignored; the same six media tests failed at `crates/buzz-relay/src/api/media.rs:1145` with `Sqlx(PoolTimedOut)` because local PostgreSQL is unavailable - three independent exact-head reviews found no correctness, security, compatibility, lifecycle-accounting, logs-only-scope, or test-adequacy finding All exact-head GitHub CI gates are green, including lint, unit tests, PostgreSQL, relay/backend/desktop integration, both Linux server cross-compiles, Windows/macOS builds, and security checks. ## Staging verification - exact multi-architecture image: `dev-sha-8faf7526822a119efa035e58b2b3c59aa67fc81d-run-33708188952-1` - immutable manifest: `sha256:26cad28266a6bb0b0e7081eb6091d374e5489f8bb78c475a4a65737dee86cc67` - image workflow: https://github.com/block/buzz/actions/runs/33708188952 - focused staging deployment: https://github.com/squareup/builderbot-platform-core-infrastructure/pull/314 - replacement ReplicaSet `buzz-d68764bc7` has two Ready pods with zero restarts - Datadog received one complete, contiguous sequence 1-12 from each pod; both end with `process_telemetry/terminal/succeeded` at 3 ms - queries scoped to the replacement ReplicaSet return no data for the removed `buzz_startup_phase_terminal` or `buzz_startup_phase_duration_seconds` families The experimental Row 7 was removed from the Buzz Startup & Rollout Safety dashboard. This logs-only PR deliberately adds no replacement dashboard row. --- **Update Sep 3, 12:26 ET:** Clarified the review boundary: this PR does not close the broader #7238. Later exporter-task termination is pre-existing runtime behavior and is now explicitly tracked in #7284; no production code or staged image changed in this update. Generated with Codex Signed-off-by: Ravneet Arora <rarora@squareup.com>
370 lines
19 KiB
Markdown
370 lines
19 KiB
Markdown
# Testing
|
||
|
||
## Automated Tests
|
||
|
||
```bash
|
||
just test-unit # unit tests — no infrastructure needed
|
||
just test # unit + integration (starts Docker if needed)
|
||
```
|
||
|
||
`just test` runs unit tests plus integration tests against Postgres and Redis
|
||
(started automatically if not already running). Neither task runs the E2E suites in
|
||
`buzz-test-client` — those are marked `#[ignore]` and require a running relay:
|
||
|
||
```bash
|
||
# Start a relay first (see below), then:
|
||
cargo test -p buzz-test-client -- --ignored
|
||
```
|
||
|
||
### Review-Proven Test Standards
|
||
|
||
Mined from the last 25 PRs' review threads (see Review-Proven Rules in
|
||
[AGENTS.md](AGENTS.md)); this is the test-quality rule reviewers litigated
|
||
most:
|
||
|
||
**Regression tests must bind the production seam and be falsifiable.**
|
||
A guard whose removal doesn't fail any test protects nothing — mutations
|
||
survived the full mobile suite twice (PRs #6996, #7013). Don't bind a
|
||
regression test to a test-only helper instead of the production code
|
||
path (PR #7013). Give pure predicates a table test over the full input
|
||
combination space (PR #6807). Scope Playwright locators — unscoped
|
||
`getByText` in a required smoke test is a strict-mode flake (PR #6980).
|
||
(PRs #6807, #6980, #6996, #7013)
|
||
|
||
---
|
||
|
||
## Live Local Relay
|
||
|
||
The fastest way to exercise the relay end-to-end is to build the release
|
||
binaries once, run `buzz-relay`, and drive it with the `buzz` CLI. The
|
||
CLI signs every request with NIP-98, so you don't need `nak` or hand-rolled
|
||
`curl`.
|
||
|
||
### 1. Setup
|
||
|
||
```bash
|
||
. ./bin/activate-hermit # activate pinned toolchain
|
||
just bootstrap # create .env and its stable relay key once
|
||
just setup # start Docker services, run migrations
|
||
```
|
||
|
||
> **Already running Buzz Desktop?** Desktop uses the same Docker container
|
||
> names (`buzz-postgres`, `buzz-redis`) and the same
|
||
> default ports (`:5432`, `:6379`). `just setup` will reuse those
|
||
> services, so **your test relay writes into Desktop's database**. That's
|
||
> fine for read/write smoke tests, but: `just reset` wipes Desktop's data
|
||
> along with yours. If you need isolation, stop Desktop first or run the
|
||
> dev stack on a different Compose project
|
||
> (`COMPOSE_PROJECT_NAME=buzz-dev docker compose …`).
|
||
|
||
`just reset` wipes all local data and starts over — **including Buzz
|
||
Desktop's data** if its services are sharing your dev stack (see callout
|
||
above).
|
||
|
||
> **Heads up — scrub stale env first.** If your shell inherits any of
|
||
> `BUZZ_AUTH_TAG`, `BUZZ_RELAY_URL`, or `BUZZ_PRIVATE_KEY` from a
|
||
> prior session (or a staging config), `unset` them before continuing.
|
||
> A stale `BUZZ_AUTH_TAG` fails the **local dev relay** with
|
||
> `auth_error: signature verification failed` on the first CLI write —
|
||
> it is *not* tolerated.
|
||
> ```bash
|
||
> unset BUZZ_AUTH_TAG BUZZ_RELAY_URL BUZZ_PRIVATE_KEY
|
||
> ```
|
||
|
||
### 2. Build the binaries
|
||
|
||
```bash
|
||
cargo build --release -p buzz-relay -p buzz-cli -p buzz-admin
|
||
export PATH="$PWD/target/release:$PATH"
|
||
```
|
||
|
||
Rebuild after any code change — the steps below use the release binaries.
|
||
|
||
### 3. Start the relay
|
||
|
||
In a separate terminal (it runs in the foreground):
|
||
|
||
```bash
|
||
set -o allexport
|
||
source .env # includes the key generated by just bootstrap
|
||
set +o allexport
|
||
buzz-relay # release binary from step 2, serves ws://localhost:3000
|
||
# alternatives:
|
||
# cargo run --release -p buzz-relay # rebuild + run in release
|
||
# just relay # DEBUG build — fast to launch on a hot cache,
|
||
# # but mismatched if step 2 left you on release.
|
||
# # Use `just relay-release` if you want the recipe.
|
||
```
|
||
|
||
Verify it's up (back in your working terminal):
|
||
|
||
```bash
|
||
curl -s http://localhost:3000/health # → ok
|
||
curl -s http://localhost:8080/_readiness # → {"status":"ready"}
|
||
```
|
||
|
||
> Health/readiness/liveness live on a **separate port** (default `8080`,
|
||
> `BUZZ_HEALTH_PORT`) so K8s probes bypass auth middleware. The main app
|
||
> port also exposes `/health` for convenience.
|
||
|
||
The relay starts in dev mode (`BUZZ_REQUIRE_AUTH_TOKEN=false`) with the stable
|
||
relay identity generated in `.env`. See the env vars table at the bottom if
|
||
you need to lock it down.
|
||
|
||
> **Already running Buzz Desktop (or another relay) on `:3000` / `:8080` /
|
||
> `:9102`?** Buzz binds three ports — main, health, metrics — and any of
|
||
> them can collide. Use a separate terminal per role and export the right
|
||
> vars in each:
|
||
>
|
||
> **In the relay terminal** (before launching `buzz-relay`):
|
||
> ```bash
|
||
> export BUZZ_BIND_ADDR=0.0.0.0:3030
|
||
> export BUZZ_HEALTH_PORT=8088
|
||
> export BUZZ_METRICS_PORT=9202
|
||
> export RELAY_URL=ws://localhost:3030 # advertised in NIP-42 challenges
|
||
> buzz-relay
|
||
> ```
|
||
>
|
||
> **In your working / CLI terminal** (for steps 4+ and the ACP harness):
|
||
> ```bash
|
||
> export BUZZ_RELAY_URL=http://localhost:3030 # CLI target
|
||
> # verify the relay on the overridden ports:
|
||
> curl -s http://localhost:3030/health # → ok
|
||
> curl -s http://localhost:8088/_readiness # → {"status":"ready"}
|
||
> ```
|
||
>
|
||
> Every snippet later in this doc shows the defaults. When you see
|
||
> `localhost:3000` / `:8080` in a code block, mentally substitute your
|
||
> overrides — or the CLI will end up talking to Buzz Desktop's relay.
|
||
|
||
> **Ignore `just setup`'s "Next steps" banner.** It still prints
|
||
> `just relay` (a debug build). Use `buzz-relay` from step 2 here —
|
||
> step 2 already built the release binary.
|
||
|
||
When you're done, stop the relay (Ctrl-C in its terminal). If it's
|
||
backgrounded or you lost the terminal: `pkill -f buzz-relay`. Leaving
|
||
it running will collide with the next reviewer who follows this doc on
|
||
the same machine.
|
||
|
||
### 4. Smoke test the CLI against the relay
|
||
|
||
End-to-end: generate an identity, create a channel, post a message, read it
|
||
back. This is the minimum sequence an agent needs to verify a local relay.
|
||
|
||
```bash
|
||
# Generate a keypair
|
||
GEN=$(buzz-admin generate-key)
|
||
export BUZZ_PRIVATE_KEY=$(echo "$GEN" | awk '/Secret key:/ {print $3}')
|
||
PUBKEY=$(echo "$GEN" | awk '/Public key:/ {print $3}')
|
||
echo "pubkey: $PUBKEY"
|
||
|
||
# Create a channel — the UUID is returned in the response
|
||
CHANNEL=$(buzz channels create --name "smoke-$$" --type stream --visibility open | jq -r '.channel_id')
|
||
echo "channel: $CHANNEL"
|
||
|
||
# Send a message and read it back
|
||
SEND=$(buzz messages send --channel "$CHANNEL" --content "hello from smoke test")
|
||
EVENT_ID=$(echo "$SEND" | jq -r '.event_id')
|
||
buzz messages get --channel "$CHANNEL" --limit 5 | jq .
|
||
|
||
# Fetch the reply chain for a specific message (empty array on a leaf — that's fine)
|
||
buzz messages thread --channel "$CHANNEL" --event "$EVENT_ID" | jq .
|
||
```
|
||
|
||
A successful run prints `{"event_id":"…","accepted":true,"message":""}` for
|
||
the send, and the message body in the `get` output. `thread` returns `[]`
|
||
for a leaf message — populated only after a reply comes in (see §6).
|
||
|
||
### 5. Verify a roster beyond 1,000 members
|
||
|
||
Use the focused live-relay script when changing channel membership, discovery,
|
||
or reconciliation. It proves the three boundaries that DB-only tests cannot:
|
||
the relay-served kind 39002 includes a member at roster position 1,501, that
|
||
identity can publish a channel message, and targeted reconciliation preserves
|
||
its discoverability.
|
||
|
||
Run this only against an isolated local database. The script inserts fixture
|
||
members directly, then drives discovery and messaging through the release CLI
|
||
and relay. Keep the release relay from step 3 running and use its configured
|
||
relay key for authoritative replacement:
|
||
|
||
```bash
|
||
export PATH="$PWD/target/release:$PATH"
|
||
export DATABASE_URL="postgres://buzz:buzz_dev@localhost:5432/buzz_roster_e2e"
|
||
export BUZZ_RELAY_URL="http://localhost:3030" # match the relay from step 3
|
||
export RELAY_URL="ws://localhost:3030"
|
||
export BUZZ_RELAY_PRIVATE_KEY="<same key used by buzz-relay>"
|
||
|
||
scripts/e2e-large-channel-roster.sh
|
||
```
|
||
|
||
Success is directly observable as four `PASS` lines. The first and fourth
|
||
include a member count greater than 1,000 and the same late-member pubkey; the
|
||
second includes the accepted kind 9 event ID, and the third proves targeted
|
||
repair left kind 39000/39001 IDs and tags unchanged:
|
||
|
||
```text
|
||
PASS discovery-before-republish channel=<uuid> members=1502 late_pubkey=<hex>
|
||
PASS late-member-action event_id=<hex>
|
||
PASS targeted-repair-preserves-metadata-and-admin-events channel=<uuid>
|
||
PASS discovery-after-republish channel=<uuid> members=1502 late_pubkey=<hex>
|
||
```
|
||
|
||
The script refuses debug binaries and refuses a `buzz` or `buzz-admin` resolved
|
||
outside this checkout's `target/release`. It also requires the targeted admin
|
||
operation to use `BUZZ_RELAY_PRIVATE_KEY`; never substitute an ephemeral signer
|
||
for an authoritative replacement.
|
||
|
||
### 6. Going deeper
|
||
|
||
For full coverage of every CLI command (54 subcommands across 12 groups),
|
||
follow [`crates/buzz-cli/TESTING.md`](crates/buzz-cli/TESTING.md).
|
||
|
||
The relay's HTTP bridge accepts three endpoints — useful if you're testing
|
||
a client other than `buzz-cli`:
|
||
|
||
| Endpoint | Purpose |
|
||
|-----------------|------------------------------------|
|
||
| `POST /events` | Submit a signed Nostr event |
|
||
| `POST /query` | NIP-01 filter query (returns events) |
|
||
| `POST /count` | NIP-45 count query |
|
||
|
||
All three accept NIP-98 auth (recommended) or, in dev mode, an `X-Pubkey`
|
||
header fallback. There is no REST API for fetching message threads — use
|
||
`POST /query` with an `#e` filter, or `buzz messages thread`.
|
||
|
||
---
|
||
|
||
## ACP Harness (optional, end-to-end with a real agent)
|
||
|
||
`buzz-acp` connects an ACP-speaking agent (goose, codex, claude code,
|
||
buzz-agent) to the relay. The harness listens for events, drives the
|
||
agent over stdio, and the agent replies through MCP tools.
|
||
|
||
Minimum recipe — assumes the relay from step 3 is running and the channel
|
||
`$CHANNEL` from step 4 still exists. The agent identity must be **different**
|
||
from the sender identity (`BUZZ_ACP_RESPOND_TO=anyone` still skips events
|
||
the agent signed itself).
|
||
|
||
```bash
|
||
cargo build --release -p buzz-acp
|
||
export PATH="$PWD/target/release:$PATH"
|
||
|
||
# 1. Save your sender identity from step 4 — you'll need it to @mention the agent
|
||
SENDER_SK="$BUZZ_PRIVATE_KEY"
|
||
|
||
# 2. Mint a fresh agent identity and capture its pubkey
|
||
AGENT_GEN=$(buzz-admin generate-key)
|
||
AGENT_SK=$(echo "$AGENT_GEN" | awk '/Secret key:/ {print $3}')
|
||
AGENT_PUBKEY=$(echo "$AGENT_GEN" | awk '/Public key:/ {print $3}')
|
||
|
||
# 3. Add the agent as a member of $CHANNEL — still using the sender identity.
|
||
# Skip this and the agent boots to "discovered 0 channel(s) → agent will
|
||
# sit idle" and silently ignores every mention.
|
||
buzz channels add-member --channel "$CHANNEL" --pubkey "$AGENT_PUBKEY" --role member
|
||
|
||
# 4. Switch to the agent identity and start it.
|
||
# buzz-acp wants ws:// (not http://). If you set BUZZ_RELAY_URL to an
|
||
# http:// URL in step 3, set the ws:// equivalent here — same host/port.
|
||
export BUZZ_PRIVATE_KEY="$AGENT_SK"
|
||
export BUZZ_RELAY_URL=ws://localhost:3000 # match step 3 (e.g. ws://localhost:3030 if overridden)
|
||
export BUZZ_ACP_RESPOND_TO=anyone # default is owner-only; opens the gate for testing
|
||
# NIP-AE core-memory prompt injection is on by default; set BUZZ_ACP_NO_MEMORY=true to opt out.
|
||
export GOOSE_MODE=auto # must be 'auto' or goose hangs on prompts
|
||
|
||
buzz-acp # foreground; logs to stdout (run in a separate terminal)
|
||
|
||
# Optional: turn on per-turn tracing if the default log is too quiet.
|
||
# RUST_LOG=buzz_acp=debug buzz-acp
|
||
```
|
||
|
||
> **Using a different ACP agent?** The default recipe assumes `goose` is on
|
||
> `$PATH` and configured (`goose --version` should print). For codex / claude
|
||
> code / buzz-agent, set `BUZZ_ACP_AGENT_COMMAND` and `BUZZ_ACP_AGENT_ARGS`
|
||
> accordingly — see `crates/buzz-acp/README.md`. Without these, buzz-acp
|
||
> will fail to spawn the agent subprocess on startup.
|
||
|
||
If you started the agent before adding it to the channel, just run the
|
||
`add-member` afterwards — it picks up the membership notification live and
|
||
subscribes without restart (`membership notification: subscribing to new channel …`).
|
||
|
||
The justfile also ships `just goose key="$AGENT_NSEC"` (foreground) and
|
||
`just goose-bg key="$AGENT_NSEC"` (background screen session) which set the
|
||
same env. See `crates/buzz-acp/README.md` for parallel agents, heartbeats,
|
||
respond-to gates, and forum subscriptions.
|
||
|
||
To exercise deferred ACP startup, add `BUZZ_ACP_LAZY_POOL=true` before launching
|
||
`buzz-acp`. The harness should connect, authenticate, subscribe, and publish
|
||
online presence without starting the configured ACP child. The first accepted,
|
||
flushable mention should start exactly one child and then dispatch the queued
|
||
message. Automated coverage in `pool_lifecycle_state` pins single-wake,
|
||
retry/backoff, and stale-result behavior; it does not replace this real
|
||
relay/process smoke test.
|
||
|
||
Send the agent a task — switch your shell back to the **sender** identity
|
||
from step 4 and @mention the agent:
|
||
|
||
```bash
|
||
export BUZZ_PRIVATE_KEY=$SENDER_SK # the key from step 4
|
||
buzz messages send --channel "$CHANNEL" \
|
||
--content "Hey agent, reply PONG only."
|
||
|
||
# Wait 10–90s, then read the channel — the agent's reply is a kind:9 from
|
||
# AGENT_PUBKEY. The current ACP build is quiet on stdout during a turn, so
|
||
# `buzz messages get` is how you confirm it ran.
|
||
buzz messages get --channel "$CHANNEL" --limit 5 | jq '.[] | {pubkey, content}'
|
||
```
|
||
|
||
Replies are kind:9 in the same channel; `buzz messages thread --channel <id>
|
||
--event <event_id>` fetches the reply chain for a specific mention.
|
||
|
||
---
|
||
|
||
## Configuration reference
|
||
|
||
The relay reads all configuration from environment variables. Defaults work
|
||
out of the box with `just setup` or `just relay`. Common overrides:
|
||
|
||
| Variable | Default | Notes |
|
||
|-----------------------------------|-----------------------------|-------|
|
||
| `BUZZ_BIND_ADDR` | `0.0.0.0:3000` | Main app port |
|
||
| `BUZZ_HEALTH_PORT` | `8080` | `/_liveness`, `/_readiness` |
|
||
| `BUZZ_METRICS_PORT` | `9102` | Prometheus `/metrics` |
|
||
| `RELAY_URL` | `ws://localhost:3000` | Advertised in NIP-11 / NIP-42 challenges. **Note: no `BUZZ_` prefix.** |
|
||
| `DATABASE_URL` | `postgres://buzz:buzz_dev@localhost:5432/buzz` | |
|
||
| `REDIS_URL` | `redis://localhost:6379` | |
|
||
| `BUZZ_REQUIRE_AUTH_TOKEN` | `false` | When true, REST requires NIP-98 (no `X-Pubkey` fallback) |
|
||
| `BUZZ_REQUIRE_RELAY_MEMBERSHIP` | `false` | When true, only pubkeys in `relay_members` can connect |
|
||
| `BUZZ_DRAIN_JITTER_MS` | `0` (off) | Per-connection upper bound, in ms, for the random delay before each live WebSocket gets its `1012 Service Restart` close on graceful shutdown. `0` closes every socket at once (the previous behavior). A positive value spreads closes uniformly over `[1, value]` ms to avoid a reconnect thundering herd on rolling deploys. Values above `20000` are capped to `20000` (`MAX_DRAIN_JITTER_MS`) to leave close-frame delivery headroom under the relay's 30s hard-drain timeout. Empty or whitespace-only is treated as unset (off); a non-integer fails startup loudly. |
|
||
| `BUZZ_AUDIT_ENABLED` | `true` | Tamper-evident event/media audit log. Set `false`/`0`/`off` to skip its DB pool and writes. Does not disable the separate moderation audit trail. |
|
||
| `BUZZ_AUTO_MIGRATE` | `false` | Opt in with `true`/`1`/`yes`/`on` to run embedded SQLx migrations on relay startup |
|
||
| `RELAY_OWNER_PUBKEY` | unset | Bootstrapped as `owner` in `relay_members` at first start |
|
||
| `BUZZ_ALLOW_NIP_OA_AUTH` | `false` | Enable NIP-OA owner attestation for membership |
|
||
| `BUZZ_WEB_DIR` | unset (source), `/srv/buzz/web` (container) | Directory containing the invite landing bundle; the production container enables it so `/invite/{code}` always works |
|
||
| `BUZZ_SERVE_GIT_WEB_GUI` | `false` | Set to `true` or `1` to expose the bundled Git repository browser at `/` and `/repos/...`; invite routes do not depend on this flag |
|
||
|
||
CLI-side, only two matter for testing:
|
||
|
||
| Variable | Default | Notes |
|
||
|-------------------------|--------------------------|-------|
|
||
| `BUZZ_RELAY_URL` | `http://localhost:3000` | CLI relay base; accepts `ws(s)://` and normalises |
|
||
| `BUZZ_PRIVATE_KEY` | — (**required**) | `nsec1…` or 64-char hex |
|
||
| `BUZZ_AUTH_TAG` | unset | Optional NIP-OA owner attestation JSON |
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
| Symptom | Cause | Fix |
|
||
|---------|-------|-----|
|
||
| `relay error 500` or `400: restricted: not a channel member` after a code change | Stale binary | Rebuild and re-export `PATH`; or `cargo run` directly |
|
||
| `Address already in use` on relay start (os error 48 on macOS, 98 on Linux) | Another relay (or stale process) holding `:3000` / `:8080` / `:9102` (or your override ports) | Metrics-listener failures emit a `metrics_bind` lifecycle terminal with reason `bind`. Check the configured ports with `lsof -iTCP:3000,8080,9102 -sTCP:LISTEN` (or your override equivalents). Kill the offender (`pkill -f buzz-relay`) or use the port-override block in step 3. If you already overrode and *still* collide, a prior reviewer left a relay running on the same alt ports — kill it or pick fresh ports |
|
||
| `auth_error: BUZZ_PRIVATE_KEY is required` | Env not exported into the CLI's shell | `export BUZZ_PRIVATE_KEY=...` (or pass `--private-key`) |
|
||
| `auth_error: BUZZ_AUTH_TAG verification failed … signature verification failed` | A stale `BUZZ_AUTH_TAG` inherited from a parent shell. The local dev relay rejects it. | `unset BUZZ_AUTH_TAG` (see the scrub block in step 1) |
|
||
| `auth-required: verification failed` on a closed relay | NIP-OA attestation needed | Set `BUZZ_AUTH_TAG` to the owner-issued JSON, or relax `BUZZ_REQUIRE_RELAY_MEMBERSHIP` |
|
||
| `channels list` empty after `channels create` | The CLI doesn't echo the channel UUID; use the filter shown in step 4 | Or `POST /query` with `{"kinds":[39002]}` |
|
||
| ACP agent ignores all events | `BUZZ_ACP_RESPOND_TO=owner-only` (default) with no owner configured | Set `BUZZ_ACP_RESPOND_TO=anyone` for testing |
|
||
| ACP logs `discovered 0 channel(s)` / `no channel subscriptions resolved` | Agent identity isn't a member of any channel | `buzz channels add-member --channel "$CHANNEL" --pubkey "$AGENT_PUBKEY" --role member` from another identity |
|
||
| `GOOSE_MODE` warning, agent hangs | Not set | `export GOOSE_MODE=auto` |
|
||
| Tests pass locally but CI fails | Forgot to run `just ci` | `just ci` runs the gate (fmt, clippy, unit tests, desktop/web builds) |
|