Skip to content

feat(agent-channels): visualize relationships and outcomes - #8

Draft
tellaho wants to merge 4 commits into
block:mainfrom
tellaho:tho/agent-channel-map
Draft

tellaho wants to merge 4 commits into
block:mainfrom
tellaho:tho/agent-channel-map

Conversation

@tellaho

@tellaho tellaho commented Sep 11, 2026

Copy link
Copy Markdown

Category: new-feature
User Impact: Users can now trace where agents work and see which pull requests associated with that work have merged or remain in flight.

Problem: Agent activity is spread across channels, while the visible outcomes of that work live separately in GitHub. A relationship list alone makes it hard to see collaboration patterns or connect signed channel activity to shipped work.

Solution: Turn Agent channels into a visual dashboard with a focused relationship map and an Outcomes lens. The page extracts pull requests directly shared by agents, enriches them through a typed provider boundary, and visualizes the signed path from agent to channel to branch to current GitHub state without claiming authorship or causation.

File changes

crates/plugin-manager/src/lib.rs
Adds the Agent channels manifest to the native bundled-plugin catalog.

crates/plugin-manager/tests/management.rs
Verifies the bundled ID is reserved and independently configurable.

docs/agent-channels.md
Documents relationship evidence, visual dashboard behavior, outcomes semantics, limits, and truthful states.

docs/plugin-architecture.md
Adds the page and external-object provider capability to the architecture map.

src/app/pages.integration.test.mjs
Covers page registration, rendering, disable/re-enable, shared service lifetime, and GitHub outcomes composition.

src/app/services.ts
Provides the typed external-object service at the app boundary.

src/bundled/agent-channels/AgentChannelsPage.tsx
Builds the agent overview, focused relationship map, visual shipping paths, outcome inspector, responsive states, and accessible list fallbacks.

src/bundled/agent-channels/dashboard.ts
Projects reusable agent summaries and bounded one-hop focus networks from relationship records.

src/bundled/agent-channels/dashboard.test.ts
Covers dashboard ordering, totals, and focused collaborator limits.

src/bundled/agent-channels/index.tsx
Registers the dashboard with its relay and object-data dependencies.

src/bundled/agent-channels/manifest.json
Defines the enabled-by-default bundled dashboard plugin.

src/bundled/agent-channels/outcomes.ts
Extracts and deduplicates canonical PR references from signed agent-authored messages while retaining evidence.

src/bundled/agent-channels/outcomes.test.ts
Covers canonical deduplication, evidence ordering, and exclusion of unsupported or untrusted observations.

src/bundled/agent-channels/relationships.ts
Builds graph-ready agent, channel, and relationship records from exact identities, authorized rosters, and bounded activity reads.

src/bundled/agent-channels/relationships.test.ts
Covers identity grouping, membership confidence, authorization filtering, projection limits, fair read budgets, and safe pagination.

src/bundled/github/index.tsx
Lets GitHub contribute typed object details independently from its existing panel UI.

src/bundled/index.ts
Adds Agent channels to the browser bundled-plugin catalog.

src/features/objects/service.ts
Introduces the typed, contribution-based external-object data boundary.

src/features/objects/service.test.ts
Covers provider resolution, loading, disposal, and faulty matcher isolation.

src/features/panels/service.test.tsx
Provides the new object service in the GitHub plugin lifecycle fixture.

src/shared/styles/globals.css
Exposes semantic success colors to the dashboard utilities.

tests/browser/agent-dashboard.spec.mjs
Exercises agent focus, mobile behavior, visual shipping paths, outcome selection, and signed evidence in Chromium and WebKit.

tests/browser/layout.spec.mjs
Updates whole-app navigation coverage for the dashboard page.

tests/fixtures/agent-channels.html
Provides a dedicated rendered fixture entry point.

tests/fixtures/agent-channels.tsx
Provides representative agents, channels, PR states, and branches for rendered inspection.

Reproduction steps

  1. Run Buzz with a selected community, a local agent library, and the GitHub plugin enabled.
  2. Open Agent dashboard and select agents to see their channel and collaborator relationships redraw around the focused agent.
  3. Switch to Outcomes to see each signed agent share flow through its channel and branch into a merged or open pull request.
  4. Select a shipping path and confirm the inspector shows repository, branch, change size, sharing agents, channels, and signed message evidence.
  5. Resize to a narrow viewport and confirm the page remains contained, with the dense visual available through horizontal exploration and the outcome list below.

Screenshot

Agent Outcomes dashboard showing visual shipping paths from agents through Buzz channels and branches into merged or open GitHub pull requests

Validation

  • bin/pnpm typecheck
  • bin/pnpm exec biome check --error-on-warnings src/bundled/agent-channels/AgentChannelsPage.tsx tests/browser/agent-dashboard.spec.mjs
  • bin/pnpm exec vitest run src/features/panels/service.test.tsx src/features/objects/service.test.ts src/bundled/agent-channels src/app/pages.integration.test.mjs (19 passed)
  • pre-push related unit suite (30 passed)
  • bin/pnpm exec playwright test --config tests/browser/playwright.config.mjs --project=chromium --no-deps tests/browser/agent-dashboard.spec.mjs (1 passed)
  • bin/pnpm exec playwright test --config tests/browser/playwright.config.mjs --project=webkit --no-deps tests/browser/agent-dashboard.spec.mjs (1 passed)
  • Rendered dark-theme inspection at 1214 × 1000 and narrow overflow assertion at 390 × 844

Full just scan remains deferred while this is a visual feedback draft.

@tellaho

tellaho commented Sep 11, 2026

Copy link
Copy Markdown
Author

Resolved the live Relay request failed (400) blocker in d04a35a.

  • Cause: the activity scan grouped up to 300 explicit channel IDs into one filter, while the live Buzz relay accepts at most 128 and returns 400 {"error":"too many explicit channels"} for 129+.
  • Fix: cap each activity query at 128 channels while preserving the existing aggregate event budget and fair allocation across batches.
  • Regression: added a 129-channel boundary test that requires two filters (128 + 1) and asserts no request exceeds the relay limit.
  • Live re-check: the owner’s current shape—29 active identities across 500 visible channels—completed as four requests (128 / 128 / 128 / 116), all HTTP 200.
  • Verification at d04a35a: owning relationship suite 10/10; TypeScript typecheck; Biome; diff check. Full Vitest: 645 passed, with the same two unrelated baseline failures in features/panels/service.test.tsx and features/relay/prepared.test.ts.

Fresh self-review found no further actionable issue in this fix.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Changes requested: three P2 correctness/integration findings.

Reviewed head d04a35a5912154210e7641a2a6b5cb8dd0d4bda1 against base 5ff5982591efdda5c52dc770a303911fd25434ef. Both independent review lanes returned before this consolidated review. Findings below were reproduced against the exact page/relationship/session source with signed synthetic events and a controlled transport on macOS Chromium 148.0.7778.96. No live account or production relay was used.

P2: Recover an interrupted activity read after same-session invalidation

Anchor: AgentChannelsPage.tsx:125–138, plus cleanup at 158 and disabled Refresh at 271.

A live disconnect, access revocation, or cache clear can clear session.agentLibrary to idle without replacing the session (session.ts:137–159,841–850,897–910). The effect then aborts its pending activity read, but neither cleanup nor its new ineligible branch clears activity.status = "loading". The mount-only library refresh at 106–109 does not run again, and Refresh is disabled while activity is loading. Live re-establishment refreshes generic observed views, not this finite read/library.

Reproduction: open the page with a ready roster/library, keep its activity request pending, and deliver the actual session’s connected → disconnected transition. The library becomes idle, the request aborts, and the DOM remains “Updating relationships…” with its only Refresh button disabled. No error/retry appears; remounting is required.

Smallest fix: leave cancelled/ineligible reads in a retryable non-loading state, and either refresh cleared library/archive evidence on same-session recovery or keep an explicit recovery action usable. Add a mounted-page regression for interruption followed by retry/re-establishment, not only session-object replacement.

P2: Do not restart the whole activity scan when only a channel preview changes

Anchor: AgentChannelsPage.tsx:120–122, used as an effect dependency at 164.

channelIds is newly allocated whenever channels.channels changes, even when all IDs remain identical. The shared store replaces that array for ordinary preview changes (store.ts:146–185,1010–1110). Consequently every new human message in an authorized channel cancels the current multi-batch activity scan and starts again from its newest page, although this page does not use channel previews. A busy community can prevent the finite scan from completing while repeatedly consuming the shared reader/background budget.

Reproduction: with one unchanged authorized channel and one library agent, hold an activity read pending. Deliver three signed messages by a different human via the actual live-session callback. Activity request count rises from 2 to 5, with each previous pending request aborted; no agent identities or channel IDs changed.

Smallest fix: stabilize the read’s authorized-channel-ID dependency by value, independently of preview/name changes. Continue recomputing the displayed graph for roster/member changes. A preview-only update should not cancel/reissue the activity read; a real scope/ID change should.

P2: Derive pagination cursors from finite relay rows, not merged observations

Anchor: relationships.ts:269–280.

Public session.read() merges its finite response with matching live observations received during the read and matching local operations (session.ts:575–590, projection.ts:42–71). Filtering out only delivery === "accepted" does not recover the original relay page: remote live observations have no delivery marker, and confirmed local seen records also pass. An older appended observation becomes the pagination cursor and skips intervening newer history.

Reproduction: the finite transport has 1,000 matching messages at timestamps 2000…1001. Without concurrent traffic, this function returns all 1,000 and the second request uses until: 1501. Inject one signed matching live observation at timestamp 1000 during the first finite request: the second request instead uses until: 1000; the result contains only 501 records and omits all 500 messages at 1500…1001. This is the real createRelaySession merge path, not a mock of session.read.

Smallest safe fix: use an existing or narrowly defined session read contract that preserves finite-page cursor evidence separately from overlays, or explicitly choose a non-paginated bounded sample instead of inventing a cursor from the merged view. Do not bypass session authorization/verification or add a page-owned relay connection. Regression coverage must include an older concurrent observation through the actual session.

Validation and scope

The browser/native catalogs agree on the enabled-by-default ID; page disable/re-enable uses existing contribution lifetime without disposing the shared session. Scope+generation remounts correctly isolate explicit community/session replacement. Exact identity mapping and current authorized-channel filtering remain intact. The three findings concern same-session recovery, read invalidation, and sampling, not an authorization bypass or durable data loss.

The exact-head hosted snapshot has successful Semgrep OSS and DCO checks, but no hosted test/build gate in the rollup. The PR is draft and currently conflicting; those are separate integration notes, not additional code findings. The author reports broad Vitest/Playwright failures in the description; their attribution to pre-existing/unrelated causes was not independently established here. No broad suites were duplicated.

Non-blocking: preserve the partial-roster caveat for empty/search-empty results too; its current footer is hidden when there are zero rows. The timestamp formatter can also throw on values outside JavaScript Date’s range that the client event type permits, but I did not establish such a value’s delivery through the Buzz relay, so this is hardening rather than a fourth blocker.

Exit criteria: the three regressions above pass against the repaired head, with no broader storage, relay, or UI redesign required. No approval submitted.

tellaho and others added 2 commits September 13, 2026 04:54
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
@tellaho
tellaho force-pushed the tho/agent-channel-map branch from d04a35a to 10564d0 Compare September 13, 2026 14:55
tellaho and others added 2 commits September 13, 2026 05:37
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
@tellaho tellaho changed the title feat(agent-channels): add agent channel relationship page feat(agent-channels): visualize relationships and outcomes Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants