Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d0aeb0c
feat(projects): add agent and CLI project-home support
thomaspblock Aug 23, 2026
c1bbbbe
fix(projects): authenticate channel home routing
Aug 23, 2026
c675967
fix(projects): validate reused repo binding
Aug 23, 2026
9855f14
feat(projects): make project creation channel-first (#6591)
thomaspblock Aug 23, 2026
66af3b9
feat(channels): support project-home channel surfaces (#6594)
thomaspblock Aug 23, 2026
63ae41a
feat(projects): make the home channel the project surface (#6595)
thomaspblock Aug 23, 2026
1fbe18c
fix(projects): address review feedback
Aug 24, 2026
8cbd94e
fix(projects): scope agent membership mutations
Aug 24, 2026
a58e235
fix(projects): refresh and exhaust project lookups
Aug 24, 2026
b47a106
fix(projects): preserve authoritative project context
Aug 24, 2026
5f73c68
refactor(desktop): keep channel panes within size ratchet
Aug 24, 2026
dbccee3
test(projects): cover causal discovery and create races
Aug 24, 2026
957374a
fix(projects): verify fallback repository winner
Aug 24, 2026
e52f4b8
test(desktop): enter repository workspace for project thread
Aug 24, 2026
50b3e06
feat(projects): unify navigation and reviewed channel requests
thomaspblock Aug 23, 2026
8786d80
polish(projects): streamline overview navigation and state (#6600)
thomaspblock Aug 24, 2026
537e1db
feat(projects): finish multi-repository workspace flows (#6602)
thomaspblock Aug 24, 2026
5e6f22b
feat(desktop): prototype channel project features on channel-first stack
matt2e Aug 25, 2026
fba8bff
feat(desktop): move channels into project sections
matt2e Aug 25, 2026
7bca513
fix(desktop): survive unmounted editor views and listener teardown races
matt2e Aug 25, 2026
b8aab59
feat(desktop): restore project workspace for channels
matt2e Aug 25, 2026
cefb430
feat(desktop): gate project channel navigation
matt2e Aug 25, 2026
63efb9a
feat(desktop): add project channel tabs
matt2e Aug 25, 2026
1c8cc9a
feat(sidebar): nest project channels under disclosure
matt2e Aug 25, 2026
673094b
fix(sidebar): inline project channels
matt2e Aug 25, 2026
a7db15d
Group project repository views under Repos
matt2e Aug 25, 2026
067805a
Sync project channel moves with Channels tab
matt2e Aug 25, 2026
e14e931
Hide inferred feature status labels
matt2e Aug 25, 2026
a15c158
Add Reviews as a channel feature
matt2e Aug 25, 2026
5a3c2ab
feat: add project widget canvas POC
matt2e Aug 26, 2026
edd53a3
Merge remote-tracking branch 'origin/main' into jitter/channel-projec…
matt2e Aug 26, 2026
1345dec
chore: satisfy channel file size ratchet
matt2e Aug 26, 2026
49d582b
feat(desktop): expand project canvas widgets
matt2e Aug 26, 2026
7f07724
feat(desktop): add full project canvas tab
matt2e Aug 26, 2026
69c86ce
feat(desktop): clarify channel view tabs
matt2e Aug 27, 2026
5d9108f
Merge remote-tracking branch 'origin/main' into jitter/channel-projec…
matt2e Aug 27, 2026
6e1df6a
refactor(desktop): extract channel join banner
matt2e Aug 27, 2026
468ad2b
feat(desktop): add project canvas demo dashboards
matt2e Aug 27, 2026
3edbfe7
feat(desktop): add Henry Gloopie to chore board
matt2e Aug 27, 2026
5fe7d6e
refactor(desktop): expand project canvas preview
matt2e Aug 27, 2026
735f1fc
feat(desktop): refine project dashboard widgets
matt2e Aug 27, 2026
2cff5d2
feat(desktop): polish home and review canvases
matt2e Aug 27, 2026
e559330
Use member profiles in active channels widget
matt2e Aug 27, 2026
ca9e4f0
feat(desktop): add project meetings widget
matt2e Aug 27, 2026
6f05643
Merge remote-tracking branch 'origin/main' into jitter/channel-projec…
matt2e Aug 27, 2026
a613381
feat(desktop): sandbox project canvas packages
matt2e Aug 28, 2026
ec5e339
Merge remote-tracking branch 'origin/main' into jitter/channel-projec…
matt2e Aug 28, 2026
17f8339
feat(canvas): notify local widget updates
matt2e Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion crates/buzz-acp/src/base_prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `buzz` CLI is your primary interface. Auth env vars: `BUZZ_RELAY_URL`, `BUZZ
| `buzz agents` | `draft-create`, `draft-update` |
| `buzz messages` | `send`, `get`, `thread`, `search` |
| `buzz channels` | `list`, `get`, `create`, `join`, `members` |
| `buzz canvas` | `get`, `set` |
| `buzz canvas` | `get`, `set`, `notify` |
| `buzz reactions` | `add`, `remove` |
| `buzz dms` | `list`, `open` |
| `buzz users` | `get`, `set-profile`, `presence` |
Expand All @@ -41,10 +41,28 @@ A project is a named grouping (`kind:30621`) with a home channel. Creating a sec
- To add tasks: `buzz issues create --channel <current-channel-uuid> --subject "…" --content "…"`. That uses this project's repository and creates one bound to the channel if none exists. `--repo-owner` / `--repo-id` remain valid once a repository exists. Session todos and markdown plans do not appear on the project.
- To add another channel to this project: `buzz projects add-channel --home-channel <current-channel-uuid> --name "…" [--template "…"]`. This opens an owner-reviewed request in Buzz Desktop and uses the project-aware channel primitive after approval. Do **not** use `buzz channels create` for a channel that should belong to the current project, and do not claim the channel exists until the owner approves it.

## Projects

A project is a named grouping (`kind:30621`) with a home channel. Creating a second project with the same name produces a duplicate card in Buzz Desktop — never do that for work that already has a project.

- If you are in a project's home channel, or a project with that name/slug already exists, do **not** run `buzz projects create`. `<context>` includes a Project block when this channel is a project home — tasks, repositories, and files you create belong to that project.
- To add a codebase: `buzz repos create --id <id> --name "…" --channel <current-channel-uuid>`. `mkdir` in `REPOS/` is not a Buzz repository.
- To add tasks: `buzz issues create --channel <current-channel-uuid> --subject "…" --content "…"`. That uses this project's repository and creates one bound to the channel if none exists. `--repo-owner` / `--repo-id` remain valid once a repository exists. Session todos and markdown plans do not appear on the project.
- To add another channel to this project: `buzz projects add-channel --home-channel <current-channel-uuid> --name "…" [--template "…"]`. This opens an owner-reviewed request in Buzz Desktop and uses the project-aware channel primitive after approval. Do **not** use `buzz channels create` for a channel that should belong to the current project, and do not claim the channel exists until the owner approves it.

`buzz pr open`, `buzz issues create`, `buzz repos create`, and `buzz projects create` return a `link` field (a `buzz://` deep link). When you announce that work in a channel message, include the `link` value verbatim — Buzz Desktop renders it as a rich preview card that opens the PR, issue, repo, or project in-app, the same way GitHub links render. Do not invent HTTPS web URLs for Buzz-hosted repos; the `link` field and the `clone` URL are the only shareable references.

To assign an issue to someone, run `buzz issues assign --issue <event-id> --repo-owner <hex> --repo-id <id> --assignee <hex> --label <name>` after creating it. Remove an assignment with the matching `buzz issues unassign` arguments. Writing assignee names in the issue body or adding recipients with `issues create --to` is notification/presentation only — Buzz Desktop's Assignees rail and the "Assigned to me" filter read the signed assignment operations. Only operations signed by the issue author or repo owner are trusted for other people; anyone may assign or unassign themselves.

## Project Canvas Packages

Project widget Canvases are local packages, distinct from relay-backed channel Canvas markdown. When asked to update one, read the active nest's `CANVASES/index.json`, match the exact community and canonical `30621:<owner>:<dtag>` project coordinate, and edit only that entry's `sourcePath`. Never edit `index.json` or anything under `.runtime/`.

- Widget values live in `data/*.json`; dashboard and widget placement is declared there too, but counts as a presentation change when notifying Buzz. Presentation code lives in `widgets/*.js`, `canvas.js`, and `styles/*.css`. Assets stay in `assets/`. Declare added files in `manifest.json`, keep `canvas.js` last, and do not add `index.html`, dependencies, builds, or network access.
- After changing only one widget's data, run `buzz canvas notify --source <sourcePath> --widget <widget-id> --change data`. Buzz passes the new data to the live widget without replacing its iframe; object renderers may implement `update(currentElement, nextData, previousData, api)` to animate, while function renderers remount that widget's content.
- After changing JavaScript, CSS, layout, assets, the manifest, or other presentation behavior, run `buzz canvas notify --source <sourcePath> --widget <widget-id> --change presentation`. Buzz validates the full package and swaps in a fresh sandboxed iframe only after it renders; the manual Reload Canvas button remains available.
- Project channel and review snapshots are authoritative. Change those values through Buzz rather than editing their bundled fixture rows. `canvas notify` is local-only, requires Buzz Desktop to be running, and does not create a relay event.

## Conversational Agent Creation

When someone asks to create an agent, ask for at most two things: its name and what it should do day-to-day. Write the `--system-prompt` yourself. Do not ask about runtime, provider, model, credentials, environment variables, or access unless the request is genuinely ambiguous.
Expand Down
9 changes: 9 additions & 0 deletions crates/buzz-acp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4529,6 +4529,15 @@ mod agent_draft_prompt_tests {
.contains("add them explicitly with `buzz channels add-member` only when authorized"));
assert!(prompt.contains("never changes membership automatically"));
}

#[test]
fn shared_base_prompt_teaches_project_canvas_notifications() {
let prompt = include_str!("base_prompt.md");
assert!(prompt.contains("buzz canvas notify --source"));
assert!(prompt.contains("--change data"));
assert!(prompt.contains("--change presentation"));
assert!(prompt.contains("Never edit `index.json` or anything under `.runtime/`"));
}
}

fn default_heartbeat_prompt() -> String {
Expand Down
2 changes: 2 additions & 0 deletions crates/buzz-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ buzz messages vote --event <event-id> --direction up
# Canvas
buzz canvas get --channel <uuid>
buzz canvas set --channel <uuid> --content "# Welcome"
buzz canvas notify --source <project-canvas-dir> --widget <widget-id> --change data
buzz canvas notify --source <project-canvas-dir> --widget <widget-id> --change presentation

# Agent Memory (NIP-AE)
buzz mem ls
Expand Down
82 changes: 44 additions & 38 deletions crates/buzz-cli/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ echo "# Canvas from stdin" | buzz canvas set --channel "$CHANNEL_ID" --content -
# canvas get
buzz canvas get --channel "$CHANNEL_ID"
# Expected: raw markdown string, or: null

# Local project Canvas notification (Buzz Desktop must be running)
buzz canvas notify --source "$CANVAS_SOURCE" --widget chores --change data | jq .
buzz canvas notify --source "$CANVAS_SOURCE" --widget chores --change presentation | jq .
# Expected: accepted true; data preserves the iframe, presentation reloads it
```

### 6.3 Messages
Expand Down Expand Up @@ -587,41 +592,42 @@ buzz channels delete --channel "$FORUM_ID" | jq .
| 22 | `channels remove-member` | ☐ | Needs admin:channels |
| 23 | `canvas get` | ☐ | |
| 24 | `canvas set` | ☐ | Direct and stdin |
| 25 | `reactions add` | ☐ | |
| 26 | `reactions remove` | ☐ | |
| 27 | `reactions get` | ☐ | |
| 28 | `dms list` | ☐ | |
| 29 | `dms open` | ☐ | |
| 30 | `dms add-member` | ☐ | Needs messages:write |
| 31 | `users get` | ☐ | Self, single, batch |
| 32 | `users set-profile` | ☐ | |
| 33 | `users presence` | ☐ | |
| 34 | `users set-presence` | ☐ | online, away, offline |
| 35 | `workflows list` | ☐ | |
| 36 | `workflows create` | ☐ | |
| 37 | `workflows update` | ☐ | |
| 38 | `workflows delete` | ☐ | |
| 39 | `workflows trigger` | ☐ | |
| 40 | `workflows runs` | ☐ | |
| 41 | `workflows get` | ☐ | |
| 42 | `workflows approve` | ☐ | Validation only (needs approval gate); bare = approve, `--approved false` = deny |
| 43 | `feed get` | ☐ | |
| 44 | `social publish` | ☐ | |
| 45 | `social set-contacts` | ☐ | |
| 46 | `social event` | ☐ | |
| 47 | `social notes` | ☐ | |
| 48 | `social contacts` | ☐ | |
| 49 | `repos create` | ☐ | |
| 50 | `repos get` | ☐ | |
| 51 | `repos list` | ☐ | |
| 52 | `repos protect list` | ☐ | Empty/populated rules; unknown rules visible; malformed rule reported in validation_error |
| 53 | `repos protect set` | ☐ | Create and replace complete exact-ref rule; verify metadata is preserved |
| 54 | `repos protect remove` | ☐ | Remove exact ref; missing rule → NotFound |
| 55 | `upload file` | ☐ | |
| 56 | `pack validate` | ☐ | Local, no relay |
| 57 | `pack inspect` | ☐ | Local, no relay |
| 58 | `notes set` | ☐ | First publish, edit/carry, --clear-tags, ambiguity, empty-stdin guard |
| 59 | `notes get` | ☐ | By name, by naddr, --content-only, cross-author, ambiguous → exit 1 |
| 60 | `notes ls` | ☐ | Own, --author all, --tag, --limit |
| 61 | `notes rm` | ☐ | Delete→get 404, double-delete idempotent, missing slug → NotFound |
| 62 | `users set-status` | ☐ | Text+emoji, text only, emoji-only (`--text ""`), `--clear`, `--clear` + `--text` → exit 1 |
| 25 | `canvas notify` | ☐ | Data and presentation with Desktop running |
| 26 | `reactions add` | ☐ | |
| 27 | `reactions remove` | ☐ | |
| 28 | `reactions get` | ☐ | |
| 29 | `dms list` | ☐ | |
| 30 | `dms open` | ☐ | |
| 31 | `dms add-member` | ☐ | Needs messages:write |
| 32 | `users get` | ☐ | Self, single, batch |
| 33 | `users set-profile` | ☐ | |
| 34 | `users presence` | ☐ | |
| 35 | `users set-presence` | ☐ | online, away, offline |
| 36 | `workflows list` | ☐ | |
| 37 | `workflows create` | ☐ | |
| 38 | `workflows update` | ☐ | |
| 39 | `workflows delete` | ☐ | |
| 40 | `workflows trigger` | ☐ | |
| 41 | `workflows runs` | ☐ | |
| 42 | `workflows get` | ☐ | |
| 43 | `workflows approve` | ☐ | Validation only (needs approval gate); bare = approve, `--approved false` = deny |
| 44 | `feed get` | ☐ | |
| 45 | `social publish` | ☐ | |
| 46 | `social set-contacts` | ☐ | |
| 47 | `social event` | ☐ | |
| 48 | `social notes` | ☐ | |
| 49 | `social contacts` | ☐ | |
| 50 | `repos create` | ☐ | |
| 51 | `repos get` | ☐ | |
| 52 | `repos list` | ☐ | |
| 53 | `repos protect list` | ☐ | Empty/populated rules; unknown rules visible; malformed rule reported in validation_error |
| 54 | `repos protect set` | ☐ | Create and replace complete exact-ref rule; verify metadata is preserved |
| 55 | `repos protect remove` | ☐ | Remove exact ref; missing rule → NotFound |
| 56 | `upload file` | ☐ | |
| 57 | `pack validate` | ☐ | Local, no relay |
| 58 | `pack inspect` | ☐ | Local, no relay |
| 59 | `notes set` | ☐ | First publish, edit/carry, --clear-tags, ambiguity, empty-stdin guard |
| 60 | `notes get` | ☐ | By name, by naddr, --content-only, cross-author, ambiguous → exit 1 |
| 61 | `notes ls` | ☐ | Own, --author all, --tag, --limit |
| 62 | `notes rm` | ☐ | Delete→get 404, double-delete idempotent, missing slug → NotFound |
| 63 | `users set-status` | ☐ | Text+emoji, text only, emoji-only (`--text ""`), `--clear`, `--clear` + `--text` → exit 1 |
3 changes: 3 additions & 0 deletions crates/buzz-cli/src/commands/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,9 @@ pub async fn dispatch_canvas(cmd: crate::CanvasCmd, client: &BuzzClient) -> Resu
match cmd {
CanvasCmd::Get { channel } => cmd_get_canvas(client, &channel).await,
CanvasCmd::Set { channel, content } => cmd_set_canvas(client, &channel, &content).await,
CanvasCmd::Notify { .. } => {
unreachable!("local Canvas notifications are handled before relay setup")
}
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/buzz-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod notes;
pub mod pack;
pub mod patches;
pub mod pr;
pub mod project_canvas;
pub mod project_channel;
pub mod projects;
pub mod reactions;
Expand Down
Loading
Loading