mirror of
https://github.com/block/buzz.git
synced 2026-10-29 13:31:44 +00:00
docs: focus room model on the future workspace
Signed-off-by: Fizz <b46ef72d2feab665ebb73edf75cce1628e3e6368697f7081c51cf547d4b77a44@buzz.block.builderlab.xyz>
This commit is contained in:
26
AGENTS.md
26
AGENTS.md
@@ -26,28 +26,12 @@ and runtime evidence answer different questions.
|
||||
### Room and Object Model
|
||||
|
||||
For changes involving projects, tasks, repositories, branches, documents, or
|
||||
channel navigation, read [VISION_ROOMS.md](VISION_ROOMS.md) before designing the
|
||||
client or protocol. Apply these rules across desktop, web, mobile, CLI, and agents:
|
||||
channel navigation, read [VISION_ROOMS.md](VISION_ROOMS.md).
|
||||
|
||||
- A room is a stable channel UUID with one conversation and zero or more object
|
||||
facets, not an exclusive task/branch/repo type. One object resolves to one
|
||||
canonical room; several objects may share it. A task and branch can be the
|
||||
**same room**. Do not create a second chat merely to add a view.
|
||||
- Resolve by community-scoped object identity, never display names. Preserve
|
||||
task nesting and branch-to-repository links even when navigation shows a tree.
|
||||
- Containment, context inheritance, and access control are separate. Nesting or
|
||||
linking must not grant membership, privatize global records, or change Git
|
||||
ACLs. Repo `buzz-channel` is security-sensitive; project binding is not repo
|
||||
authority.
|
||||
- Do not invent per-client relationship encodings or conflict winners. Shared
|
||||
metadata must round-trip through relay persistence/discovery and supported
|
||||
writers; handle unsupported fields, conflicts, retries, and partial creation.
|
||||
- Preserve one conversation and its history across views. Migrating issue/PR
|
||||
comments needs an explicit compatibility plan, not silent duplicate streams.
|
||||
A branch merge must not archive other active facets sharing its room.
|
||||
|
||||
The vision's metadata extension is proposed, not a shipped API. These guardrails
|
||||
constrain new work; they do not authorize an implicit data migration.
|
||||
A room has one conversation and can have several object views. Each object has
|
||||
one canonical room; a task and its branch can share the **same room**. Do not
|
||||
create a second conversation merely to add a view. Apply this model consistently
|
||||
across desktop, web, mobile, CLI, and agents.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ Beyond chat: channels are workspaces.
|
||||
|
||||
The relay hosts git repos. Smart HTTP — standard `git clone`, `git push`, nothing special. Your npub signs pushes. Same domain, same auth, same identity as everything else on the relay.
|
||||
|
||||
The target is **one room, many views**. Projects, tasks, repositories, branches, and documents resolve to canonical conversation rooms; a task and its branch can share the same channel UUID. Rooms nest for navigation without changing permissions. See [VISION_ROOMS.md](VISION_ROOMS.md) for the cross-client conceptual contract and the boundary between existing behavior and proposed backend support.
|
||||
The target is **one room, many views**. Projects, tasks, repositories, branches, and documents resolve to canonical conversation rooms; a task and its branch can share the same channel UUID. Time-bound projects can span durable repositories, each with its own ongoing room. See [VISION_ROOMS.md](VISION_ROOMS.md) for the shared model, nested relationships, and backend specification.
|
||||
|
||||
In that model, creating a feature branch creates or reuses its room — CI results, review comments, and the merge decision belong there. A completed branch-only room can archive into a permanent record; merging a branch must not archive other active work sharing the room.
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ This document is the software-forge slice of the broader Buzz platform. [VISION.
|
||||
|
||||
The shared room contract is [VISION_ROOMS.md](VISION_ROOMS.md): a project, repo,
|
||||
task, branch, or document is a facet of a canonical room, not an exclusive channel
|
||||
type. Several facets may share one conversation. The room model and automatic
|
||||
lifecycle described here are product direction, not a claim that provisioning,
|
||||
comment migration, or inheritance already ships.
|
||||
type. Several facets may share one conversation. Projects organize time-bound
|
||||
outcomes across repositories; repository rooms support ongoing code and
|
||||
maintenance discussion.
|
||||
|
||||
A project lives on the relay. `myproject.com` in a browser shows the project home. Click a repo and you're at `repoa.myproject.com` — README rendered, file tree navigable, code syntax-highlighted, clone URL at the top. The same URL serves HTML to a browser and git protocol to `git clone`. Content negotiation. One URL, two audiences.
|
||||
|
||||
@@ -194,7 +194,7 @@ Every step traced. Every trace a signed event. Change the project CI once and ev
|
||||
|
||||
Bug reports and tasks retain their NIP-34 kind:1621 identity. In the target model, task details, forum presentation, and branch work can open the same canonical room; subtasks can have nested rooms. A forum is a view, not a reason to fork the conversation.
|
||||
|
||||
NIP-22 kind:1111 is the intended portable threaded-comment representation in this forge vision; current issue/PR clients use separate kind:1 comments. Unifying these with room chat requires the explicit read/write compatibility transition described in [VISION_ROOMS.md](VISION_ROOMS.md#rollout-boundaries). Labels, assignees, and milestones remain object metadata, not channel identity.
|
||||
Threaded comments use NIP-22 kind:1111. Labels, assignees, and milestones are nostr tags. Design discussions and RFCs use the forum's long-form async surface.
|
||||
|
||||
NIP-34 clients can discover and interact with issues. Buzz's forum gives them a home with threading, search, and agent triage.
|
||||
|
||||
@@ -241,7 +241,7 @@ Standard kinds as substrate. Custom kinds only where genuinely novel.
|
||||
| Layer | Standard NIP Kinds | Buzz Custom | Rationale |
|
||||
|-------|-------------------|---------------|-----------|
|
||||
| **Git state** | 30617, 30618, 1617, 1618, 1621, 1630-1633 (NIP-34) | — | Interop with ngit, gitworkshop.dev |
|
||||
| **Comments (target)** | 1111 (NIP-22) | — | Portable threading; transition from current kind:1 comments remains to be designed |
|
||||
| **Comments** | 1111 (NIP-22) | — | Threaded replies everywhere |
|
||||
| **Channels** | 9000-9022, 39000-39003 (NIP-29) | — | Project workspaces |
|
||||
| **HTTP auth** | 27235 (NIP-98) | — | Git push authentication |
|
||||
| **Agent identity** | 0 (NIP-01 profile) | — | Agents are npubs |
|
||||
|
||||
230
VISION_ROOMS.md
230
VISION_ROOMS.md
@@ -1,183 +1,105 @@
|
||||
# Buzz Rooms — One Conversation, Many Views
|
||||
|
||||
**Status: product direction; not a shipped protocol.** This document defines the
|
||||
shared conceptual contract for desktop, web, mobile, CLI, and agent integrations.
|
||||
The backend shape below is a proposal to review before implementation, not an API
|
||||
clients may assume exists. [VISION.md](VISION.md) covers the platform;
|
||||
[VISION_PROJECTS.md](VISION_PROJECTS.md) covers its software-forge workflows.
|
||||
|
||||
## The Model
|
||||
|
||||
A **room is a channel**: one stable channel UUID and one working conversation.
|
||||
Projects, tasks (including subtasks), repositories, branches, and living documents
|
||||
each resolve to a canonical room. They are **facets** of that room, not mutually
|
||||
each have a canonical room. They are **facets** of that room, not mutually
|
||||
exclusive room types. An ordinary conversation can have no object facets.
|
||||
|
||||
One object has one canonical conversation home within its community. One room can
|
||||
be home to several objects. A task and its implementation branch can therefore
|
||||
be two views of **the same channel UUID**, not separate channels with synchronized
|
||||
messages. Switching from task details to the diff changes the view, not the
|
||||
conversation, membership, or history. Adding a facet does not create another chat.
|
||||
One object has one conversation home. One room can be home to several objects.
|
||||
A task and its implementation branch can therefore be two views of **the same
|
||||
channel UUID**, not separate channels with synchronized messages. Switching from
|
||||
task details to the diff changes the view, not the conversation. Adding a facet
|
||||
does not create another chat.
|
||||
|
||||
Object state stays in its own representation: a task still has status and
|
||||
assignees, a repository still has refs, and a document still has content. The room
|
||||
connects those representations; it does not turn every object into a chat message
|
||||
or replace NIP-34 records with channel rows.
|
||||
Object state stays in its own representation: a task has status and assignees,
|
||||
a repository has refs, and a document has content. The room brings these views
|
||||
and their conversation together.
|
||||
|
||||
### Identity Is Not a Label
|
||||
## Projects and Repositories
|
||||
|
||||
Resolve objects and rooms by stable identity, scoped to the active community:
|
||||
Projects organize a time-bound outcome. Repositories are durable homes for code
|
||||
and ongoing conversation. A project can span several repositories, and a
|
||||
repository can support many projects over time or concurrently. Their rooms have
|
||||
different purposes and do not normally share a one-to-one relationship.
|
||||
|
||||
| Object | Identity to resolve, not a display-name heuristic |
|
||||
|---|---|
|
||||
| Room | Channel UUID |
|
||||
| Project | Address `30621:<owner-pubkey-hex>:<project-id>` |
|
||||
| Repository | Address `30617:<owner-pubkey-hex>:<repo-id>` |
|
||||
| Task / subtask | Issue event ID (`kind:1621` today) |
|
||||
| Branch | Repository address **and full ref**, e.g. `refs/heads/fix-login` |
|
||||
| Initial document view | The channel's canvas, identified by its channel UUID |
|
||||
|
||||
A room rename does not change its identity. The same branch name in two repos is
|
||||
two different objects. Newer repository/project metadata events replace state at
|
||||
the same address; their event IDs are not new object identities. A branch rename
|
||||
or deletion/recreation needs an explicit binding/lifecycle policy, not a guess
|
||||
based on a matching label. Independently addressable documents beyond canvases
|
||||
need their own agreed identity contract before implementation.
|
||||
|
||||
## Nesting Without Losing Relationships
|
||||
|
||||
Rooms can nest. A single parent gives navigation a tree (or a forest of root
|
||||
rooms); the full object relationships remain a graph. For example:
|
||||
For example, a **Simplify sign-in** project spans the identity service and mobile
|
||||
app repositories:
|
||||
|
||||
```text
|
||||
Project room P [project + default repository]
|
||||
├── Task room T [task: Improve sign-in]
|
||||
│ └── Subtask room S [task: Fix login + branch: refs/heads/fix-login]
|
||||
└── Design room D [document: sign-in design canvas]
|
||||
Project room: Simplify sign-in
|
||||
├── Task room: Improve account recovery
|
||||
│ ├── Room S: Fix recovery tokens [subtask + identity-service branch]
|
||||
│ └── Room M: Add recovery screen [subtask + mobile-app branch]
|
||||
└── Design room: Recovery experience [document]
|
||||
|
||||
Repository room: identity-service [ongoing code and maintenance discussion]
|
||||
└── Branch view: fix-recovery-tokens → room S
|
||||
|
||||
Repository room: mobile-app [ongoing code and maintenance discussion]
|
||||
└── Branch view: recovery-screen → room M
|
||||
```
|
||||
|
||||
The subtask and branch both open room S. S remains nested under T, while its branch
|
||||
still belongs to the repository in P. A repository view may also link to S; that
|
||||
is another route to the same room, not a second parent or another conversation.
|
||||
A dedicated repository room is also valid; sharing the default repository with
|
||||
the project home is not mandatory for every repository.
|
||||
The subtask and branch in S open the same room; likewise for M. The repository
|
||||
branch listings link to those rooms rather than creating new conversations.
|
||||
Completing the sign-in project does not end either repository's ongoing work.
|
||||
|
||||
Project membership still comes from the project's repository references
|
||||
([NIP-MP](docs/nips/NIP-MP.md)); nesting rooms does not redefine it. A repository
|
||||
can belong to several projects and still have one canonical room. Room nesting
|
||||
also does not by itself define task dependencies or a claimable-work queue.
|
||||
When several task facets share a room, room containment alone cannot identify
|
||||
which task is another task's parent; that needs an explicit object relationship.
|
||||
## Nested Rooms and Relationships
|
||||
|
||||
### Three Separate Decisions
|
||||
Rooms nest to organize work: a project contains task rooms, a task contains
|
||||
subtask rooms, and a document can have its own room or be a view of an existing
|
||||
room. A channel canvas is the document view within a room.
|
||||
|
||||
1. **Containment/navigation:** where a room appears and how users find it.
|
||||
2. **Context:** which parent guidance or related documents an agent should read.
|
||||
3. **Access:** who may read, write, administer, or push.
|
||||
A room has at most one containment parent. The navigation tree is not the entire
|
||||
relationship model: a task's room can sit under its project while its branch
|
||||
still belongs to a repository elsewhere. Project-to-repository links and
|
||||
branch-to-repository links remain available independently of that tree. Multiple
|
||||
routes to a room all lead to the same conversation.
|
||||
|
||||
A parent link or object association does not grant access, copy membership, or
|
||||
inherit permissions. Context inheritance is a separate, explicit, permission-
|
||||
checked policy; a link is not permission to read everything behind it. Navigation
|
||||
must not expose inaccessible parent/child metadata. An unreadable or unresolved
|
||||
room does not justify inventing a replacement room or hiding an otherwise
|
||||
readable object.
|
||||
## Access
|
||||
|
||||
**Existing repository bindings are security-sensitive:** `buzz-channel` on a
|
||||
repository announcement participates in hosted Git access control. The same tag
|
||||
on a project is navigation metadata, not authority over its repositories. New
|
||||
room associations must neither overwrite the repo's ACL binding as a navigation
|
||||
convenience nor become a second, competing source of Git permissions. Linking a
|
||||
community-visible issue or project to a private room does not make it private.
|
||||
A room and its object views should feel like one workspace. Someone admitted to
|
||||
that workspace should be able to read its conversation and the objects presented
|
||||
as part of it, rather than encountering an arbitrary inaccessible subset. The
|
||||
same principle applies when presenting nested rooms as a shared project workspace.
|
||||
Reading the work and permission to push, merge, or administer it are distinct
|
||||
capabilities.
|
||||
|
||||
## What Exists Today
|
||||
The permissions design must make that experience consistent across linked rooms
|
||||
and objects. For repositories, it must choose whether access is governed through
|
||||
the canonical room relationship or through repository permissions coordinated
|
||||
with the room. The model does not prescribe a separate, unrelated channel link
|
||||
just for Git authorization. The choice of permission authority and inheritance
|
||||
rules remains an explicit design decision; the required user experience is
|
||||
coherent access, not disconnected permission islands.
|
||||
|
||||
This is the implementation baseline inspected at `2ac0aa1dd`, not a claim that
|
||||
all of the target model has shipped:
|
||||
## Backend Specification
|
||||
|
||||
| Existing behavior | Source |
|
||||
|---|---|
|
||||
| Desktop project creation provisions a home channel and default repo sharing that home | [createProject.ts](desktop/src/features/projects/createProject.ts) |
|
||||
| Projects and repos are signed addressable events; tasks are issue events, not dedicated task rows | [NIP-MP](docs/nips/NIP-MP.md), [SDK builders](crates/buzz-sdk/src/builders.rs), [events schema](migrations/0001_initial_schema.sql) |
|
||||
| Channels have persisted rows; discovery metadata is reconstructed from supported fields | [channel store](crates/buzz-db/src/store/channel.rs), [side effects](crates/buzz-relay/src/handlers/side_effects.rs) |
|
||||
| Hosted Git uses the repo's channel binding for access, and object storage for Git data | [binding.rs](crates/buzz-relay/src/api/git/binding.rs), [store.rs](crates/buzz-relay/src/api/git/store.rs) |
|
||||
| Task creation does not provision a task room; issue/PR comments are separate `kind:1` records | [issueMutations.ts](desktop/src/features/projects/issueMutations.ts), [project hooks](desktop/src/features/projects/hooks.ts) |
|
||||
| Project/issue/Git records remain community-scoped even when carrying an `h` provenance tag | [ingest.rs](crates/buzz-relay/src/handlers/ingest.rs), [CLI command guidance](crates/buzz-cli/src/commands/mod.rs) |
|
||||
Persist room relationships on the channel:
|
||||
|
||||
The channel store does not yet provide general room hierarchy or multi-object
|
||||
bindings. Branch ref state is not a branch-room registry. Threads, huddle parent
|
||||
links, sidebar sections, and lists of related channels are not substitutes for
|
||||
shared room containment. The agent harness's [current-room canvas context](crates/buzz-acp/src/queue.rs)
|
||||
does not implement inherited parent context.
|
||||
- `parent_channel_id`: nullable channel UUID, in the same community, indexed for
|
||||
child lookup.
|
||||
- `object_bindings`: a list of typed object references stored as JSONB. A room
|
||||
can bind several objects, including a task and its branch.
|
||||
|
||||
## Smallest Proposed Backend Extension
|
||||
Bindings reference the object they represent: an issue ID for a task, an
|
||||
addressable project or repository coordinate, or a repository coordinate plus
|
||||
full Git ref for a branch. Object records retain their own state; the bindings
|
||||
connect them to their conversation home.
|
||||
|
||||
Keep the channel UUID, conversation, membership, and object event models. Extend
|
||||
persisted channel metadata with:
|
||||
Expose these fields through signed channel create (`9007`), edit (`9002`), and
|
||||
metadata discovery (`39000`) events. No feature-specific HTTP endpoint is needed.
|
||||
Edits can set or clear the parent and replace the binding list. Omitted fields
|
||||
remain unchanged; parent clearing and an empty binding list are explicit actions.
|
||||
Persist a metadata edit atomically and return the same relationships on discovery.
|
||||
|
||||
- An optional `parent_channel_id` in the same community, indexed for child lookup.
|
||||
- An `object_bindings` list of typed stable references; JSONB is sufficient for an
|
||||
initial representation. Several bindings may point into one room.
|
||||
The relay validates management authority, bounded binding shapes, and an existing
|
||||
same-community parent. It rejects self-parenting and cycles, including concurrent
|
||||
moves that would create a cycle.
|
||||
|
||||
Illustrative binding values are a task issue ID, a repository/project address,
|
||||
or a repository address plus full branch ref. These are **conceptual field
|
||||
names**, not finalized database columns, tag spellings, or SDK types.
|
||||
|
||||
Use the existing signed channel create (`9007`), edit (`9002`), and discovery
|
||||
metadata (`39000`) path. No feature-specific HTTP endpoint is needed. Proposed
|
||||
edit semantics are explicit set/clear of the parent and replacement of the
|
||||
binding list, with unrelated metadata preserved. The implementation must specify
|
||||
omission, clearing, concurrent edits, and older-client round trips before rollout.
|
||||
Arbitrary client-added tags do not persist merely because a create/edit event
|
||||
accepts them: storage and discovery serialization must both support the fields.
|
||||
|
||||
The relay must enforce channel-management authority, bounded/valid binding
|
||||
shapes, an existing same-community parent, no self-parenting or cycles (including
|
||||
concurrent moves), and atomic metadata updates. It must enforce access on
|
||||
relationship discovery as well as writes. Cross-object authority needs an
|
||||
explicit resolution rule: managing a room is not authority to hijack somebody
|
||||
else's object's canonical home. Existing owner-signed project/repo bindings must
|
||||
be reconciled, not silently overruled by room-side claims.
|
||||
|
||||
A global unique-binding constraint is not required for the first metadata
|
||||
increment. **Canonicality is still the product contract**, not permission for
|
||||
each client to choose its own winner. Before enabling canonical-room creation,
|
||||
define one shared resolution/reconciliation rule for conflicting claims and
|
||||
idempotent retries. Surface unresolved conflicts instead of choosing whichever
|
||||
room a client happened to discover first. Clients may create/reuse rooms on
|
||||
object creation or discovery, but must recover from partial object/room creation
|
||||
without silently provisioning duplicates. Metadata alone does not solve races.
|
||||
|
||||
## Rollout Boundaries
|
||||
|
||||
- **One conversation needs a transition.** Issue/PR comments currently have a
|
||||
separate event stream; the forge vision also discusses NIP-22 comments. A
|
||||
follow-up must define compatible reads, one authoritative write destination,
|
||||
provenance, deduplication, and access behavior before claiming a unified room
|
||||
conversation. Do not start dual-writing copies of messages or discard history.
|
||||
- **Automation is separate.** Client-on-discovery provisioning can come first.
|
||||
Creating a room for a Git push while every client is offline needs a persistent
|
||||
hook/worker. Document which guarantee an implementation actually provides.
|
||||
- **Lifecycle follows all facets.** A branch merge may archive a branch-only
|
||||
room; it must not automatically archive an active task or project sharing that
|
||||
room. Unlinking/deleting an object must not erase shared conversation history
|
||||
or cascade-delete other facets. Shared-room archive policy needs explicit UX.
|
||||
- **Private objects and inheritance are not included.** Private task records,
|
||||
inherited access, inherited harness context, workflow inheritance, standalone
|
||||
document objects, and richer relationship/dependency graphs need separate
|
||||
designs. Do not infer them from the proposed metadata fields.
|
||||
|
||||
## Implementation Review Checklist
|
||||
|
||||
- Do desktop, web, mobile, CLI, and agents resolve the same object to the same
|
||||
channel UUID, including retries, conflicts, and community switching?
|
||||
- Can a task gain a branch view without replacing its identity or conversation?
|
||||
- Do both task nesting and branch-to-repository relationships survive navigation?
|
||||
- Are unsupported/unresolved bindings handled without guessed names, duplicate
|
||||
rooms, unauthorized disclosure, or a second conversation stream?
|
||||
- Are membership, object ownership, repository ACLs, and context policies unchanged
|
||||
unless the change explicitly designs and tests a new authorization contract?
|
||||
- Do persistence, edits, discovery, SDKs, and clients round-trip the same metadata?
|
||||
|
||||
Related requests: [channel hierarchy #3667](https://github.com/block/buzz/issues/3667)
|
||||
and [issue relationships #3728](https://github.com/block/buzz/issues/3728). This
|
||||
vision establishes direction; it does not close either implementation request.
|
||||
All clients use the same relationships to resolve an object's canonical room.
|
||||
Creating another view reuses that room. Repeated creation requests must converge
|
||||
on the same room rather than create parallel conversations. Conflicting bindings
|
||||
must be reconciled consistently across clients, not resolved by local discovery
|
||||
order. The metadata storage does not require a global unique-binding constraint.
|
||||
|
||||
Reference in New Issue
Block a user