feat(projects): add agent and CLI project-home support - #6590
Conversation
Give agents bounded project-home context and project-aware CLI operations while keeping channel matching client-filtered through the existing relay query surface. Signed-off-by: Thomas Petersen <thomasp@squareup.com>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra adversarial/security review — needs work
The red Unit Tests job is not caused by this diff: it fails linking untouched buzz-voice with could not find native static library 'sherpa-onnx-c-api'. That check should be retried rather than patched in this projects PR.
I found two source-level blockers independently while tracing the new project-home resolution.
P1 — Any relay writer can hijack a channel's agent project context and redirect channel-scoped issues (confidence 100)
Evidence
crates/buzz-acp/src/prompt_project.rs:23-25:!event_is_unlisted(event) && event_has_tag_value(event, "buzz-channel", channel_id)crates/buzz-acp/src/prompt_project.rs:27-33: the matching events are ordered only bycreated_at, then the first parseable event wins.crates/buzz-cli/src/commands/project_channel.rs:27-31:let project = pick_oldest_listed(&projects);followed byif let Some(member) = first_member_repo(event) { return Ok(member); }docs/nips/NIP-MP.md:139:`buzz-channel` on a project is **metadata only**.docs/nips/NIP-MP.md:188:The relay MUST NOT check whether the signer owns, maintains, or has any relationship to a member repository.
Trigger scenario
- An attacker who knows a project channel UUID publishes a listed
kind:30621carrying thatbuzz-channeland anatag for the attacker's repository. This is protocol-valid and requires no authority over the channel. - The attacker gives it an earlier accepted timestamp than the legitimate project (or simply publishes before project creation).
- ACP selects that event as the channel's project home and promotes its name/owner/repository into generated
[Context]instructions. buzz issues create --channel <victim-channel>independently makes the same oldest-event choice and returns the attacker's first member coordinate without checking that the project signer controls the channel or that the member repo is actually bound to it.- A normal “create a task in this project” request is therefore signed against an unrelated attacker-chosen repository.
This crosses an integrity boundary: unauthenticated project metadata is being treated as authoritative routing configuration. Resolve the project from an authenticated channel-owned binding/type, or require a verifiable relationship between the selected project signer and channel authority. At minimum, channel-scoped repo resolution must verify the selected 30617 is bound to the requested channel and reject ambiguous projects rather than choosing oldest.
P1 — Global slug squatting lets any signer block another user's project creation (confidence 100)
Evidence
crates/buzz-cli/src/commands/projects.rs:373-379:other_listed_project(&fetch_projects_by_dtag(client, slug).await?, &caller_pubkey)causes a conflict when any other pubkey has the slug.docs/nips/NIP-MP.md:134:Only the signer can replace their (pubkey, 30621, d) coordinate.docs/nips/NIP-MP.md:194:newest created_at wins per (pubkey, 30621, d), and one pubkey can never overwrite another's coordinate.
Trigger scenario
An attacker publishes listed projects for common slugs (app, website, a known upcoming product name). Every later buzz projects create <slug> by every other identity is rejected locally, even though the protocol intentionally namespaces projects by signer. The suggested error action (“Add a repository to that project instead”) cannot work because editing is signer-only. Do not impose relay-wide uniqueness on an owner-namespaced coordinate; duplicate-card prevention needs an authority-scoped rule.
Additional adversarial risk retained in this PR comment
crates/buzz-cli/src/commands/project_channel.rs:178-185 adds the selected foreign project owner as a maintainers tag on an implicitly created caller-owned repository. Under docs/nips/NIP-MP.md:215-217, that tag is sufficient claim authority for the foreign signer. I did not live-test Desktop's resulting fold, but this should be removed or explicitly justified before merge; untrusted project metadata must not grant provenance/claim authority over a newly created repo.
Coverage: full 12-file diff read; traced ACP project lookup → generated context, CLI channel lookup → issue creation, implicit repo creation, project collision checks, NIP-MP authority and claim semantics. I did not mutate the branch or run a live hostile relay reproduction.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra re-review of 7a9af2ac — one routing blocker remains
The original two P1 findings are fixed in the authoritative-selection path: foreign channel/project claims no longer route ACP or CLI, ambiguity fails closed, cross-signer slug/channel squatting is removed, and implicit repo creation no longer grants foreign maintainers authority.
P1 — Existing same-id repository bypasses the new channel-binding check (confidence 100)
Evidence
crates/buzz-cli/src/commands/project_channel.rs:181-188:if let Some(existing) = crate::commands::repos::fetch_own_repo_announcement(client, &repo_id).await? { let _ = try_add_own_repo_to_channel_project(client, channel, &repo_id).await; return Ok(ChannelProjectRepo { repo_owner: existing.pubkey.to_hex(), repo_id, }); }
- The new binding check exists in
repo_from_announcementat lines 94-104, but this fallback does not call it.
Trigger scenario
- The caller already owns repo
30617:<caller>:app, bound to channel A (or unbound). - They own a repository-empty project home with slug
appin channel B. buzz issues create --channel Bfinds no authoritative project/member and no caller-owned repo bound to B, then reachesensure_default_repo.fetch_own_repo_announcement("app")returns the channel-A repository. The code attaches it to the channel-B project and returns it without checking or rebinding itsbuzz-channel.- The issue is silently created against channel A's unrelated repository. Subsequent calls repeat the same misrouting, while ACP correctly refuses to recognize that member as authoritative for B.
The fallback must apply the same first-buzz-channel equality invariant before returning. If an existing same-id repo is bound elsewhere, fail with an actionable conflict or choose a non-colliding id; do not attach or route to it.
Advisory — maintainer authorization reads only the first value (confidence 75)
Evidence
crates/buzz-cli/src/commands/project_channel.rs:88-91:|| repo.tags.iter().any(|tag| { matches!(tag.as_slice(), [name, value, ..] if name == "maintainers" && value.eq_ignore_ascii_case(&signer)) })
crates/buzz-acp/src/prompt_project.rs:93-101likewise returns onlytag.get(1)for eachmaintainerstag.VISION_PROJECTS.md:27and NIP-34 modelmaintainersas a multi-value tag; Desktop deliberately reads all values (desktop/src/features/projects/projectModels.ts:283-285).
A valid ['maintainers', first, project_signer] repository authorizes the signer in Desktop but is rejected by both new routing implementations. Iterate all values after the tag name so ACP, CLI, and Desktop share one authority rule.
Re-review coverage: exact fix diff a6c5f1db..7a9af2ac; traced authoritative selection, ambiguity, project creation collisions, implicit repo fallback, and maintainer parsing. Report-only; no branch mutation.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra final security/authority re-review — findings cleared at 7bbed3f1
No remaining security or adversarial findings in the incremental fix.
Verified:
crates/buzz-cli/src/commands/project_channel.rs:197-205now callsrequire_repo_channel_bindingbefore reusing or attaching a same-slug existing repository, so a repository bound to channel A cannot route a channel-B issue.require_repo_channel_bindinguses the firstbuzz-channelvalue, matching the relay's fail-closed binding semantics, and rejects both mismatched and absent bindings.- ACP's
multi_tag_valuesand CLI'stag.as_slice()[1..]now inspect every pubkey value in everymaintainerstag, matching NIP-34/Desktop semantics. - Regressions cover the mismatched existing binding and authorization by a later maintainer value.
- The prior fixes remain intact: project-home selection requires a channel-bound live member repository plus signer authority; ambiguity fails closed; cross-signer slug/channel squatting is absent; implicit creation does not grant foreign maintainer authority.
Verdict for my security/authority lane: merge-ready at exact head 7bbed3f127f25559fc301044842ee6582b2fdc9a. CI and independent correctness review are outside this verdict and were still in progress when checked.
## Summary - create explicit NIP-MP projects with a home channel and default repository - preserve standalone repository folding, project deletion, and deterministic repository selection - restore Template, Team, visibility, and agent settings in the project creation flow This is Part 2 of the channel-first Projects stack, following #6590. It is independently based on `main`; Part 3 adds the project-home channel surface. ## Testing - focused project collection, creation, channel, and model tests: 38/38 passed - Desktop unit suite: 5,415/5,415 passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - create listed and unlisted projects with and without templates in the first staging Desktop session - healthy signals: one home channel, one default repository, stable project coordinates, and no duplicate legacy card - failure signals: partial project creation, duplicate projects, missing default repository, or stale sidebar entries; mitigate by reverting this PR --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com>
## Summary - classify and render project-home channels through the shared channel glyph and lifecycle helpers - let the normal channel pane host a project idle auxiliary surface and focus drawer - align channel management, headers, member bars, and empty-channel actions with project channel semantics This is Part 3 of the channel-first Projects stack, based on #6591. Part 4 adds the project-home navigation and context experience. ## Testing - focused channel lifecycle, pane helper, and project-home channel tests: 7/7 passed - Desktop unit suite: 5,422/5,422 passed - E2E-mode Desktop build passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - open normal, temporary, private, and project-home channels in the first staging Desktop session - healthy signals: normal channels retain their existing composer/thread behavior and project homes use the project glyph and auxiliary slot - failure signals: missing composer, incorrect channel kind, stuck focus drawer, or project chrome on a normal channel; mitigate by reverting this PR --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
## Summary - render an explicit project's home channel through the normal channel timeline and composer - add a resizable project context rail with codebase, channel, people, and workspace navigation - keep project agent conversations bounded to the project home and preserve repository/detail routes This is Part 4 of the channel-first Projects stack, based on #6594. The final part contains overview and workspace completion polish. ## Testing - focused project conversation, route, summary, workspace-sheet, and related-channel tests: 39/39 passed - Desktop unit suite: 5,439/5,439 passed - E2E-mode Desktop build passed - TypeScript, Biome, and differential file-size checks passed - full pre-push gate passed ## Post-Deploy Monitoring & Validation - open project homes from project and channel entry points in the first staging Desktop session - healthy signals: one channel timeline/composer, stable repository context, bounded project agent history, and reversible workspace sheets - failure signals: duplicate channel surfaces, stale repository selection, unrelated DM history, or sheets replacing the channel route; mitigate by reverting this PR Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
| fn truncate_repo_name(name: &str) -> String { | ||
| if name.len() <= 128 { | ||
| return name.to_string(); | ||
| } | ||
| name.chars().take(128).collect() | ||
| } |
There was a problem hiding this comment.
The guard measures bytes but the truncation takes chars, while build_repo_announcement rejects names over 128 bytes. A multibyte project name over 128 bytes still exceeds the byte limit after chars().take(128), so default-repo creation errors instead of truncating (e.g. a 100-CJK-character name). Same pattern in projects.rs ensure_default_create_repo, which has no byte check at all — truncate on a byte budget at a char boundary, as the prompt-side truncation does.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: both default-repository paths now share UTF-8-safe truncation on a 128-byte budget, with a CJK regression test.
| const workspaceSheet = | ||
| workspaceSheetOpen && workspaceSheetTab && workspaceRepository ? ( | ||
| <ProjectHomeWorkspaceSheet | ||
| key={`${workspaceSheetTab}:${workspaceRepository.id}`} | ||
| identityPubkey={identityQuery.data?.pubkey} | ||
| onOpenCommit={handleOpenCommit} | ||
| onRepositoryAdded={handleFilesAdded} | ||
| onSelectRepository={setWorkspaceRepositoryId} | ||
| project={project} | ||
| projects={projects} | ||
| repository={workspaceRepository} | ||
| tab={workspaceSheetTab} | ||
| /> | ||
| ) : null; |
There was a problem hiding this comment.
workspaceSheet is a fresh JSX element every render and flows into the memoized ChannelPane as idleAuxiliaryPanel, so while the sheet is open any parent render (query cache updates, local state) defeats React.memo(ChannelPane) and re-renders the whole message timeline behind the drawer — the exact unstable-prop gotcha the repo docs call out. Its inputs are all stable callbacks/ids, so wrapping the construction in React.useMemo restores the memo boundary.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: the conditional workspace sheet element is memoized with its complete dependency set, preserving the downstream ChannelPane memo boundary.
| if (homeChannel) { | ||
| const alreadyMember = homeChannel.memberPubkeys.some( | ||
| (pubkey) => | ||
| normalizePubkey(pubkey) === normalizePubkey(selectedAgent.pubkey), | ||
| ); | ||
| if (!alreadyMember) { | ||
| await addChannelMembers({ | ||
| channelId: homeChannel.id, | ||
| pubkeys: [selectedAgent.pubkey], | ||
| role: "bot", | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
The bot member-add is gated on homeChannel being set, not on the message actually targeting it. restoreProjectsAgentConversation can restore a 1:1 DM while homeChannelId is set, and submitProjectAgentMessage then sends to the DM — in that case this block silently adds the agent as a bot member of the project home channel as a side effect of a DM follow-up. Guard on the resolved target, e.g. only add when !conversation || conversation.channel.id === homeChannel.id.
🤖
There was a problem hiding this comment.
Fixed in 2e0fe69: bot membership is now added only when the resolved existing conversation is the project home channel (or no conversation exists yet).
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
thomaspblock
left a comment
There was a problem hiding this comment.
Cassandra security re-review of 2e0fe6999 — one tenant-scope blocker remains
Matt's three reported defects are correctly fixed: UTF-8 names now truncate to a 128-byte prefix at a character boundary in both callers, the CJK regression passes, the workspace-sheet element has a complete useMemo dependency set, and an existing DM no longer triggers project-home membership.
P1 — Project-home membership is not bound to the captured relay/signer scope (confidence 75)
Evidence
desktop/src/features/projects/ui/ProjectAgentChatPanel.tsx:167-171:await addChannelMembers({ channelId: homeChannel.id, pubkeys: [selectedAgent.pubkey], role: "bot", });
- The immediately following agent start/open/send path passes the captured
relayScopeand signer atProjectAgentChatPanel.tsx:183-201, but this membership mutation passes neither. desktop/src/shared/api/types.ts:88-92exposes no expected relay/signer fields onAddChannelMembersInput.desktop/src-tauri/src/commands/channels.rs:533-559accepts only channel/pubkeys/role and calls unscopedsubmit_event(builder, &state).desktop/src-tauri/src/relay/submit.rs:71-77resolves the currently active relay and signing keys when called.
Trigger scenario
- The panel captures project home channel A, relay A, and signer A.
- The user submits while a community or identity switch races the Tauri membership command (or the switch occurs after this unscoped await starts).
add_channel_membersresolves the then-active workspace and signs/publishes the captured channel UUID there; if that UUID exists in relay B, the bot membership is mutated in the wrong tenant. Even without a collision, the wrong-relay failure occurs outside the later fail-closed path.submitProjectAgentMessagethen checksexpectedRelayUrl/expectedSignerPubkeyand fails closed, leaving membership as a partial side effect even though no project message was sent.
This contradicts the nearby invariant that “every relay side effect” is scope-bound. Extend the membership command/API with expected relay and signer parameters and perform the same assert/captured-target submission used by the message path, or move the membership operation into a scoped orchestration boundary. The channel-target guard fixes Matt's DM case but not this tenant race.
Verification: reviewed exact incremental diff 7d6c4abce..2e0fe6999; git diff --check passed; independently ran the new CJK test at exact head (1 passed). Report-only; no branch mutation.
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
Cassandra security/adversarial re-review —
|
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent — request changes
Reviewed base e23632941331502c0330e51d407e667bea26ef57 through exact head adff0acff7f5fbe61795aad6e3a5670e1300b45d against VISION.md, VISION_PROJECTS.md, TESTING.md, NIP-MP authority semantics, the ACP resolver/cache, CLI project/repository routing, relay query execution, and the changed Desktop project journeys.
P1 — reject a same-slug repository bound outside the new project home
crates/buzz-cli/src/commands/projects.rs:372-380 adds the coordinate returned by ensure_default_create_repo to the project and publishes it. But ensure_default_create_repo at projects.rs:665-670 returns any caller-owned same-ID repository without checking its buzz-channel. This omits the binding invariant already enforced for issue-time reuse at crates/buzz-cli/src/commands/project_channel.rs:171-182,197-205.
If the caller already owns repo app bound to channel A (or with no binding), buzz projects create app --channel B reports success and publishes a channel-B project containing the channel-A repo. ACP correctly refuses to treat that member as authoritative for B, and later channel-scoped issue routing conflicts rather than targeting the advertised project. Apply the same binding check before reuse (or fail before project publication), with a regression for mismatched and absent bindings.
P1 — do not permanently cache project absence or mutable project metadata
crates/buzz-acp/src/pool.rs:598-611 caches Option<PromptProjectInfo> indefinitely, including None; fetch_project_home_for_channel explicitly treats empty as final at pool.rs:2986-2989. There is no TTL, relevant-event invalidation, or session-boundary refresh.
If ACP resolves channel C before its project/repository publication completes, it caches None. Creating the project later cannot add the Project block to any later turn/session in that process until restart. Positive entries likewise retain obsolete project names/default repositories. Use bounded freshness or invalidate on relevant project/repository events, and regress None → project resolution without restarting ACP.
P1 — do not treat a truncated global query page as authoritative absence
The project-home paths issue one-shot 1,000-row queries: ACP at crates/buzz-acp/src/pool.rs:2993-3003, CLI projects at crates/buzz-cli/src/commands/projects.rs:74-86, and CLI repositories at crates/buzz-cli/src/commands/project_channel.rs:160-168. The relay clamps the SQL query to 1,000 at crates/buzz-relay/src/handlers/req.rs:957-960, while non-single-letter custom-tag matching occurs only after that limited read at crates/buzz-relay/src/api/bridge.rs:1308-1315; the SQL tag pushdown at req.rs:1001-1044 covers #p/#d, not #buzz-channel.
Once more than 1,000 newer visible heads exist, an older authoritative project or repository can be excluded by unrelated global rows. ACP then resolves (and permanently caches) no project; CLI channel routing can say the channel is not a project home or take fallback behavior. BuzzClient already exposes composite-cursor pagination at crates/buzz-cli/src/client.rs:683-729. Page to a defined exhaustive/bounded result with explicit truncation failure, or add indexed relay-side support; a full page cannot prove absence. Add coverage that places the authoritative head beyond page one.
Validation and residual risk
- Clean exact-head
cargo test -p buzz-cli -p buzz-acppassed (809 + 9 + 374 tests; one doc test ignored); clippy for both packages passed with-D warnings. - Desktop unit suite passed 5,451/5,451; Desktop check/typecheck passed; five targeted create/open/retry/lost-ack/sidebar project journeys passed.
- Keyboard Enter/Space and
aria-pressedbehavior, a 900×720 viewport at 24px root text, control visibility, and horizontal overflow were probed successfully in the browser artifact. No additional source-level product/accessibility blocker was found. - All applicable exact-head GitHub checks are green. Those checks do not exercise the three failure shapes above.
- Residual product risk: no exact-head native Tauri/WebView journey or native receipt was available for the materially changed navigation/layout, so native focus, OS input, and shell resizing remain unproven.
- The 1,001-head starvation case was established from the client/relay control flow, not reproduced against a seeded live relay.
Gauge correctness/testing verification of Jude's three P1s — all confirmed at exact head
|
Cassandra security/adversarial response to Jude's review — exact head
|
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
|
Merged current
Exact-head validation:
GitHub now reports the PR mergeable; required CI is running. Please re-review both prior ACP boundaries at this new merge head because the main merge changes the ACP diff. |
jedwards27
left a comment
There was a problem hiding this comment.
:bot: Jude’s code review agent
Verdict: APPROVE
Reviewed: 22cdda441d19da1b15dd7db4d932d2f067cd87b3..495f1d97b95c15b19c104acf4167ef17d046af2a (exact head 495f1d97b95c15b19c104acf4167ef17d046af2a)
The prior owner-review blocker is fixed, and the changed-head systems/merge review found no remaining author-actionable defect.
Prior blocker cleared
ProjectChannelRequestDialog.tsx:41-49 now shows a semantic Lifetime field whenever ttlSeconds is present, including the formatted requested duration and the consequence that the channel “Cleans up automatically after that period of inactivity.” Approval forwards the same request.request.ttlSeconds unchanged (useProjectChannelRequests.ts:150-159), so reviewed and applied values agree. The no-TTL path omits this copy.
The dialog uses native description-list relationships and shared Radix AlertDialog title/description, focus, action, and cancel semantics. Pending settlement disables both actions and keeps the dialog open appropriately.
Systems and merge result
Project authority still resolves once before ACP session creation or configured initial_message. Indeterminate authority returns the typed local outcome, preserves/requeues the batch, retains the healthy ACP process/session, and does not mutate crash-circuit or respawn state. The same resolved context drives prompt framing. Review of the merged-main delta found no unexpected authority/session regression; the effective database delta is the intended custom-tag SQL pushdown, activated only for the supported one-string #buzz-channel filter before LIMIT.
Exact-head evidence
- Desktop tests: 5,651/5,651 passed; typecheck passed.
- TTL regression: 2/2 passed; deleting the disclosure made the positive test fail as intended, then restoration returned it to green.
cargo test -p buzz-acp: 820 unit + 9 lifecycle tests passed.cargo test -p buzz-cli: 385 passed; one doc test ignored.git diff --checkpassed; clean trees and exact live head were rechecked by both lanes.- All exact-head GitHub checks are terminal successful or expected skipped.
Native Tauri keyboard/screen-reader observation was not run. Static semantics and deterministic coverage show no material defect; native observation remains a reviewer/tooling confidence gap, not author action.
Author action: none.
Verification owner: CI for its completed exact-head gates; reviewer/tooling for any optional native accessibility observation.
Resolve types.ts conflict: keep the canvasTypes re-export refactor from this branch; #6590 only stripped adjacent blank lines and its AddChannelMembersInput additions land outside the conflict. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…c-agent-commit-identity * origin/main: Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…enericize * origin/main: Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) fix(desktop): stop pulsing addressed agents on send (#6873) fix(desktop): prioritize sidebar channel status (#6861) feat(desktop): hyperlink selected composer text on link paste (#6684) chore(release): release Buzz Desktop version 0.5.20 (#6839) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…arer-auth * origin/main: feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
#6900) **Category:** fix **User Impact:** Sidebar mention numerals now match the user's theme/accent color and appear for mentions inside threads, not just top-level channel messages. Hover-to-preview on channel rows is unchanged. **Problem:** Follow-ups to #6696: 1. The mention numeral used a fixed red `--notification` token that ignored the user's theme and accent selection. 2. The numeral read `appBadgeCount`, which deliberately excludes threaded replies (Home's badge subtotal counts those toward the Dock badge). Mentions inside threads therefore never surfaced a numeral on the channel row — only the generic thread-activity dot. **Solution:** 1. The badge now reuses the primary accent pair (`bg-primary` / `text-primary-foreground`), the same treatment as the DM count badge, so it follows whatever accent the user applies — including the pinned neutral accent of the Buzz themes. The now-unused `--notification` tokens and Tailwind utilities are removed. 2. Non-DM rows now count every unread mention/broadcast — threaded or top-level — via a new `highPriorityCount` channel projection, replacing the boolean `highPriorityUnread` across the TS contract, the Tauri SQLite store, the e2e mock bridge, and the native test rig. The Dock/app badge projection (`appBadgeCount`) is unchanged, so Dock totals do not double-count thread activity that Home already counts. The hover-to-preview channel activity popover is untouched; e2e coverage now pins the combination (thread mention → numeral, no dot, popover still opens and lists the mentioning reply). <details> <summary>File changes</summary> **desktop/src/features/channels/useUnreadChannels.ts** Non-DM sidebar counts switch from `appBadgeCount` to the mention/broadcast-inclusive `highPriorityCount`; the high-priority channel set derives from the same count. **desktop/src/features/sidebar/ui/SidebarSection.tsx** Badge drops the fixed notification classes and inherits the accent-following default. **desktop/src/shared/styles/globals/theme.css / desktop/tailwind.config.js** Remove the unused fixed `--notification` tokens and semantic utilities. **desktop/src/shared/api/tauriObservedUnread.ts / desktop/src-tauri/src/observed_unread.rs** Projection contract: `highPriorityUnread: bool` → `highPriorityCount: u64`, aggregated per unread high-priority event. **desktop/src/testing/e2eBridge.ts / desktop/src/features/channels/observedUnreadNativeRig.mjs** Mock/native-rig projections mirror the new count field. **desktop/src/features/channels/observedUnreadNative.test.mjs** Native badge-lane test seeds a high-priority event to match the numeral's new semantics. **desktop/tests/e2e/badge.spec.ts** Top-level mention test now asserts the badge equals the applied accent (seeded `#22c55e` under an adversarial theme). New test: in-thread mention shows the numeral, no dot, and the hover preview popover still lists the mentioning reply. **desktop/tests/e2e/channel-activity-popover.spec.ts / desktop/tests/e2e/thread-unread.spec.ts** Seeded fixtures that mention the user now expect the numeral (which subsumes the dot). </details> ## Reproduction steps 1. Pick any theme + accent color in Settings → Appearance. 2. Receive a top-level message mentioning you in an inactive channel → the row shows a numeral pill in your accent color. 3. Receive a reply **inside a thread** that mentions you in an inactive channel → the row shows the numeral (previously only a dot). 4. Hover the row → the channel activity preview still opens and lists the mentioning reply. 5. Switch accents/themes → the pill re-colors accordingly; the Dock badge count is unchanged from before. ## Verification - `tsc --noEmit`, Biome, `check:px-text` — clean - Desktop unit tests: 179/179 channel-suite; full suite has one pre-existing failure from #6590 (`useRetainedProjectGitViews.test.mjs` loader error, fails on clean `main`) - Tauri Rust: `observed_unread` tests + clippy + fmt — clean - Playwright smoke: badge (19), channel-activity-popover (10), thread-unread (13), plus channels/inbox/stream/messaging/mentions suites — all green ## Screenshots Screenshots are posted in the PR discussion using immutable repository-hosted image URLs. Signed-off-by: tulsi <tulsi@block.xyz>
…cp-sessions * origin/main: fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) Signed-off-by: Salman Mohammed <smohammed@squareup.com> # Conflicts: # crates/buzz-acp/src/pool.rs
…-home + block#6842 sidebar unread-DM overflow) # Conflicts: # desktop/src/shared/api/types.ts
block#6900) **Category:** fix **User Impact:** Sidebar mention numerals now match the user's theme/accent color and appear for mentions inside threads, not just top-level channel messages. Hover-to-preview on channel rows is unchanged. **Problem:** Follow-ups to block#6696: 1. The mention numeral used a fixed red `--notification` token that ignored the user's theme and accent selection. 2. The numeral read `appBadgeCount`, which deliberately excludes threaded replies (Home's badge subtotal counts those toward the Dock badge). Mentions inside threads therefore never surfaced a numeral on the channel row — only the generic thread-activity dot. **Solution:** 1. The badge now reuses the primary accent pair (`bg-primary` / `text-primary-foreground`), the same treatment as the DM count badge, so it follows whatever accent the user applies — including the pinned neutral accent of the Buzz themes. The now-unused `--notification` tokens and Tailwind utilities are removed. 2. Non-DM rows now count every unread mention/broadcast — threaded or top-level — via a new `highPriorityCount` channel projection, replacing the boolean `highPriorityUnread` across the TS contract, the Tauri SQLite store, the e2e mock bridge, and the native test rig. The Dock/app badge projection (`appBadgeCount`) is unchanged, so Dock totals do not double-count thread activity that Home already counts. The hover-to-preview channel activity popover is untouched; e2e coverage now pins the combination (thread mention → numeral, no dot, popover still opens and lists the mentioning reply). <details> <summary>File changes</summary> **desktop/src/features/channels/useUnreadChannels.ts** Non-DM sidebar counts switch from `appBadgeCount` to the mention/broadcast-inclusive `highPriorityCount`; the high-priority channel set derives from the same count. **desktop/src/features/sidebar/ui/SidebarSection.tsx** Badge drops the fixed notification classes and inherits the accent-following default. **desktop/src/shared/styles/globals/theme.css / desktop/tailwind.config.js** Remove the unused fixed `--notification` tokens and semantic utilities. **desktop/src/shared/api/tauriObservedUnread.ts / desktop/src-tauri/src/observed_unread.rs** Projection contract: `highPriorityUnread: bool` → `highPriorityCount: u64`, aggregated per unread high-priority event. **desktop/src/testing/e2eBridge.ts / desktop/src/features/channels/observedUnreadNativeRig.mjs** Mock/native-rig projections mirror the new count field. **desktop/src/features/channels/observedUnreadNative.test.mjs** Native badge-lane test seeds a high-priority event to match the numeral's new semantics. **desktop/tests/e2e/badge.spec.ts** Top-level mention test now asserts the badge equals the applied accent (seeded `#22c55e` under an adversarial theme). New test: in-thread mention shows the numeral, no dot, and the hover preview popover still lists the mentioning reply. **desktop/tests/e2e/channel-activity-popover.spec.ts / desktop/tests/e2e/thread-unread.spec.ts** Seeded fixtures that mention the user now expect the numeral (which subsumes the dot). </details> ## Reproduction steps 1. Pick any theme + accent color in Settings → Appearance. 2. Receive a top-level message mentioning you in an inactive channel → the row shows a numeral pill in your accent color. 3. Receive a reply **inside a thread** that mentions you in an inactive channel → the row shows the numeral (previously only a dot). 4. Hover the row → the channel activity preview still opens and lists the mentioning reply. 5. Switch accents/themes → the pill re-colors accordingly; the Dock badge count is unchanged from before. ## Verification - `tsc --noEmit`, Biome, `check:px-text` — clean - Desktop unit tests: 179/179 channel-suite; full suite has one pre-existing failure from block#6590 (`useRetainedProjectGitViews.test.mjs` loader error, fails on clean `main`) - Tauri Rust: `observed_unread` tests + clippy + fmt — clean - Playwright smoke: badge (19), channel-activity-popover (10), thread-unread (13), plus channels/inbox/stream/messaging/mentions suites — all green ## Screenshots Screenshots are posted in the PR discussion using immutable repository-hosted image URLs. Signed-off-by: tulsi <tulsi@block.xyz> Signed-off-by: Bartok9 <259807879+Bartok9@users.noreply.github.com>
block#6900) **Category:** fix **User Impact:** Sidebar mention numerals now match the user's theme/accent color and appear for mentions inside threads, not just top-level channel messages. Hover-to-preview on channel rows is unchanged. **Problem:** Follow-ups to block#6696: 1. The mention numeral used a fixed red `--notification` token that ignored the user's theme and accent selection. 2. The numeral read `appBadgeCount`, which deliberately excludes threaded replies (Home's badge subtotal counts those toward the Dock badge). Mentions inside threads therefore never surfaced a numeral on the channel row — only the generic thread-activity dot. **Solution:** 1. The badge now reuses the primary accent pair (`bg-primary` / `text-primary-foreground`), the same treatment as the DM count badge, so it follows whatever accent the user applies — including the pinned neutral accent of the Buzz themes. The now-unused `--notification` tokens and Tailwind utilities are removed. 2. Non-DM rows now count every unread mention/broadcast — threaded or top-level — via a new `highPriorityCount` channel projection, replacing the boolean `highPriorityUnread` across the TS contract, the Tauri SQLite store, the e2e mock bridge, and the native test rig. The Dock/app badge projection (`appBadgeCount`) is unchanged, so Dock totals do not double-count thread activity that Home already counts. The hover-to-preview channel activity popover is untouched; e2e coverage now pins the combination (thread mention → numeral, no dot, popover still opens and lists the mentioning reply). <details> <summary>File changes</summary> **desktop/src/features/channels/useUnreadChannels.ts** Non-DM sidebar counts switch from `appBadgeCount` to the mention/broadcast-inclusive `highPriorityCount`; the high-priority channel set derives from the same count. **desktop/src/features/sidebar/ui/SidebarSection.tsx** Badge drops the fixed notification classes and inherits the accent-following default. **desktop/src/shared/styles/globals/theme.css / desktop/tailwind.config.js** Remove the unused fixed `--notification` tokens and semantic utilities. **desktop/src/shared/api/tauriObservedUnread.ts / desktop/src-tauri/src/observed_unread.rs** Projection contract: `highPriorityUnread: bool` → `highPriorityCount: u64`, aggregated per unread high-priority event. **desktop/src/testing/e2eBridge.ts / desktop/src/features/channels/observedUnreadNativeRig.mjs** Mock/native-rig projections mirror the new count field. **desktop/src/features/channels/observedUnreadNative.test.mjs** Native badge-lane test seeds a high-priority event to match the numeral's new semantics. **desktop/tests/e2e/badge.spec.ts** Top-level mention test now asserts the badge equals the applied accent (seeded `#22c55e` under an adversarial theme). New test: in-thread mention shows the numeral, no dot, and the hover preview popover still lists the mentioning reply. **desktop/tests/e2e/channel-activity-popover.spec.ts / desktop/tests/e2e/thread-unread.spec.ts** Seeded fixtures that mention the user now expect the numeral (which subsumes the dot). </details> ## Reproduction steps 1. Pick any theme + accent color in Settings → Appearance. 2. Receive a top-level message mentioning you in an inactive channel → the row shows a numeral pill in your accent color. 3. Receive a reply **inside a thread** that mentions you in an inactive channel → the row shows the numeral (previously only a dot). 4. Hover the row → the channel activity preview still opens and lists the mentioning reply. 5. Switch accents/themes → the pill re-colors accordingly; the Dock badge count is unchanged from before. ## Verification - `tsc --noEmit`, Biome, `check:px-text` — clean - Desktop unit tests: 179/179 channel-suite; full suite has one pre-existing failure from block#6590 (`useRetainedProjectGitViews.test.mjs` loader error, fails on clean `main`) - Tauri Rust: `observed_unread` tests + clippy + fmt — clean - Playwright smoke: badge (19), channel-activity-popover (10), thread-unread (13), plus channels/inbox/stream/messaging/mentions suites — all green ## Screenshots Screenshots are posted in the PR discussion using immutable repository-hosted image URLs. Signed-off-by: tulsi <tulsi@block.xyz> Signed-off-by: Bartok9 <259807879+Bartok9@users.noreply.github.com>
…ifications-pr * origin/main: Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) fix(desktop): stop pulsing addressed agents on send (#6873) fix(desktop): prioritize sidebar channel status (#6861) feat(desktop): hyperlink selected composer text on link paste (#6684) Signed-off-by: Tom Brow <tomb@block.xyz>
Reconciling slice A against current main took main's `mode="wait"` on the `AnimatePresence` that hosts the auxiliary surfaces, added by #6590 to serialize replacements. That was the wrong side to take: overlapping mount is load-bearing for the cover drawer. Replacing one cover surface with another must stay dismissable with a single Escape, and the guards that achieve it — `CoverDrawer`'s capture-phase claim standing down while exiting, and the exiting panel declining to `preventDefault` — only have something to coordinate while both surfaces are mounted at once. Under `mode="wait"` the outgoing drawer unmounts before the incoming one enters, the press lands on nothing, and the user needs a second Escape. `agent-activity-cover.spec.ts:349` asserts the overlap directly and failed deterministically (3/3 CI retries, reproduced locally); removing the attribute turns it green. Verified no regression in the behaviour #6590 was protecting: the drawer, focus-mode, thread and projects e2e specs pass (124 tests), and the comment now records why the attribute must not come back. Co-authored-by: Bradley Axen <baxen@squareup.com> Signed-off-by: Bradley Axen <baxen@squareup.com> Signed-off-by: ss-dev-00 <a02c4e0850e5e612b4ddf95dbe2f5c56467cf27c6552203bc833ff438fb31971@buzz.block.builderlab.xyz>
The Add Channel dialog rendered every row with a hardcoded '#' prefix, ignoring channel.visibility and channel.channelType. The sidebar already shows a lock for private channels and a file icon for forum channels; the channel browser drifted away from that and the same channel looked different in two surfaces of the same window (block#6120). Add a pure, unit-testable ChannelRowIcon component with getChannelRowIconKind() and use it in ChannelBrowserDialog. The sidebar now uses ChannelGlyph (introduced by block#6590), so this PR focuses on the browser surface. Tests cover the helper directly and render the component under JSDOM to assert the right lucide-* class reaches the DOM for each channel kind. Signed-off-by: Santhi Prakash <b.santhiprakash@gmail.com>
…r-contracts * origin/main: (26 commits) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) fix(desktop): stop pulsing addressed agents on send (#6873) fix(desktop): prioritize sidebar channel status (#6861) feat(desktop): hyperlink selected composer text on link paste (#6684) ... Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…h-coordinator * origin/main: (138 commits) fix(client): resurface hidden DMs from live activity (#6885) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) fix(desktop): stop pulsing addressed agents on send (#6873) fix(desktop): prioritize sidebar channel status (#6861) ... # Conflicts: # Justfile
…at-vacuum * origin/main: fix(projects): allow owners to delete agent projects (#6533) Fade expanded video controls on hover (#6926) fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822) fix(client): resurface hidden DMs from live activity (#6885) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) Signed-off-by: Luke Tornquist <tornquist@squareup.com>
…agent-edit * origin/main: (39 commits) chore(deps): update dependency vitest to v4.1.11 (#6667) chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666) chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664) fix(projects): allow owners to delete agent projects (#6533) Fade expanded video controls on hover (#6926) fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822) fix(client): resurface hidden DMs from live activity (#6885) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) ... Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…late-cardinality-hints * origin/main: (145 commits) chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663) chore(deps): update dependency vitest to v4.1.11 (#6667) chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666) chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664) fix(projects): allow owners to delete agent projects (#6533) Fade expanded video controls on hover (#6926) fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822) fix(client): resurface hidden DMs from live activity (#6885) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) ... Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
* origin/main: (21 commits) chore(deps): update rui314/setup-mold digest to 7e4f20a (#6663) chore(deps): update dependency vitest to v4.1.11 (#6667) chore(deps): update dependency @tanstack/react-virtual to v3.14.10 (#6666) chore(deps): update ubuntu:24.04 docker digest to 33ceb71 (#6664) fix(projects): allow owners to delete agent projects (#6533) Fade expanded video controls on hover (#6926) fix(db): exclude kind:30179 ciphertext from brownfield FTS (#6822) fix(client): resurface hidden DMs from live activity (#6885) fix(desktop): keep the draft space when typing right after a mention pick (#6875) broker: define the agent-to-broker action contract (#6742) fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) ... Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
…e-view * origin/pr-6189: (170 commits) test(mesh): prove relay mode probes are refreshed fix(mesh): keep closed availability helper test-only fix(mesh): refresh relay admission mode safely fix(desktop): keep project sheets independent from threads (#6901) Add gated security reviews (#6816) fix(desktop): accent-colored mention badges that count thread mentions (#6900) Add Buzz benchmark evaluation layers (#6823) fix(desktop): show edited head content in thread panel (#6887) fix(desktop-tooltip): increase surface contrast (#6897) Deduplicate ACP thread prompt context (#6706) Apply access policy when reusing channel agents (#6838) feat(sidebar): prioritize unread DMs in overflow navigation (#6842) feat(projects): add agent and CLI project-home support (#6590) feat(desktop): restore message quick reactions (#6892) Use paired tags for standing & per-turn context (#6701) fix(cli): preserve signatures in event reads (#6884) refactor(db): finish replaceable event store extraction (#6777) Fix Admin feedback filter overflow (#6825) fix(desktop): stop pulsing addressed agents on send (#6873) fix(desktop): prioritize sidebar channel status (#6861) ... Signed-off-by: Alessandro Joabar <sandro@squareup.com> # Conflicts: # desktop/src-tauri/src/commands/mesh_llm.rs # desktop/src-tauri/src/mesh_llm/catalog.rs # desktop/src/features/sidebar/ui/AppSidebar.tsx
The Add Channel dialog rendered every row with a hardcoded '#' prefix, ignoring channel.visibility and channel.channelType. The sidebar already shows a lock for private channels and a file icon for forum channels; the channel browser drifted away from that and the same channel looked different in two surfaces of the same window (block#6120). Add a pure, unit-testable ChannelRowIcon component with getChannelRowIconKind() and use it in ChannelBrowserDialog. The sidebar now uses ChannelGlyph (introduced by block#6590), so this PR focuses on the browser surface. Tests cover the helper directly and render the component under JSDOM to assert the right lucide-* class reaches the DOM for each channel kind. Signed-off-by: Santhi Prakash <b.santhiprakash@gmail.com>
Summary
This is Part 1 of the channel-first Projects stack. Part 2 contains project creation and model foundations.
Testing
cargo fmt --all -- --checkcargo clippy -p buzz-cli -p buzz-acp --all-targets -- -D warningscargo test -p buzz-cli -p buzz-acp— 1,184 tests passed, 1 doc test ignoredPost-Deploy Monitoring & Validation