Skip to content

Commit

docs: add Channels spec (chat for people and agents)

Claude-Session:
https://claude.ai/code/session_011tBfr1Kv6Bbf7dhvf3zo9c
Claude and Claude Opus 5.5committed Parent2eb8556Browse files
1 file+127−00/1 viewed
+127−0
1+# Channels
2+
3+People and agents talk in the same place the code lives. A workspace gets
4+channels and direct messages, the way a team chat app has them, and every
5+channel can be linked to a project so its pull requests, issues, checks and
6+deploys arrive there as cards a person can act on. Agents are members of
7+channels like anyone else.
8+
9+Design canvas: the "g1t Channels" artifact (v2 row is the target).
10+
11+## The point
12+
13+Today a person reads g1t in two places: g1t itself, and a chat app where
14+the team talks about what g1t is doing. Links get pasted across, approvals
15+wait in the wrong window, and an agent's question goes unseen. Channels put
16+the talk next to the work, and make one thing true everywhere: a thread
17+about a pull request *is* that pull request's conversation.
18+
19+## Product model
20+
21+- **Modes.** The shell gets a rail: Home, Code, Chat, Agents, Inbox. Code
22+ keeps today's sidebar exactly. Chat has a sidebar of its own. Inbox is
23+ shared by both. No mode's sidebar ever lists the other mode's things.
24+- **Channel.** Belongs to a workspace. Public or private. Optionally linked
25+ to one or more projects, and optionally to a team. Has members: people
26+ and agents.
27+- **Message.** Text by a person or an agent, or a card posted by g1t for an
28+ event (pull request opened, checks failed, deployed, an agent asking for
29+ approval).
30+- **Thread.** Replies under a message. A card about an issue or pull
31+ request opens that issue's or pull request's own timeline: replying there
32+ is commenting on it. Other threads belong to the channel.
33+- **Direct message.** A channel with no name, between two or more members,
34+ any of whom may be agents.
35+- **Project chat.** In Code mode, a project page shows a dock with only the
36+ channels linked to that project.
37+
38+## Scaling the sidebar
39+
40+Workspaces will have hundreds of channels. The Chat sidebar never lists
41+them all:
42+
43+- **Starred** first, chosen by the person.
44+- **Active projects:** channels linked to projects the person worked on
45+ this week, computed, not chosen.
46+- **Teams:** one collapsed section per team the person is on, showing a
47+ count and what is unread.
48+- **Direct messages**, newest first.
49+- **All / Unread / Mentions** filter, and a jump box. Everything else is
50+ behind *Browse channels* and *Muted*.
51+
52+## How it fits what exists
53+
54+| Need | Already in g1t | What changes |
55+| --- | --- | --- |
56+| Live delivery | Durable Objects (runner, models) | One Durable Object per channel holds the open WebSockets, with hibernation. D1 keeps the messages. |
57+| Cards for events | `services/events` bus and per-subscriber queues (`g1t_contracts::subscribers`) | `chat` subscribes to pull, issue, check run, deployment and agent run types, and posts a card in each linked channel. |
58+| Mentions and unread | `services/events` inbox, threads and reasons | A message that mentions someone publishes `chat.message.created`; the inbox tells them with reason `mention`. Thread keys reuse `<repo_id>#<number>`. |
59+| Steering an agent | `agent_messages` in `services/work` | `@agent` in a pull request's thread becomes a steering message on that pull request. |
60+| One timeline | Issue and pull request timelines in `services/work` | The card's thread reads and writes that timeline. Chat stores only a pointer. |
61+| Navigation | `workspace-nav.ts`, `shell.tsx` | A rail, a `mode` beside `SidebarKey`, and a Chat sidebar. |
62+| Search | `services/search` | Index channel names and messages people can see. |
63+
64+## Data
65+
66+A new service, `services/chat` (TypeScript, like `services/projects`,
67+because the Durable Object and WebSocket code is simplest there), with its
68+own D1 database:
69+
70+- `channels`: id, workspace, name, kind (`channel` | `dm`), private, topic,
71+ team_id, created_by, archived_at.
72+- `channel_links`: channel_id, project_id. What makes a channel a
73+ project's chat, and where cards go.
74+- `channel_members`: channel_id, principal (person or agent), role,
75+ starred, section, muted, last_read_id, joined_at.
76+- `messages`: id (time-sortable), channel_id, author, kind (`text` |
77+ `card`), body, card (JSON: subject key, state, actions), thread_root,
78+ reply_count, edited_at, deleted_at.
79+- `reactions`: message_id, principal, emoji.
80+
81+Unread counts come from `last_read_id` against the newest message id, kept
82+in the channel's Durable Object, so the sidebar needs one read per
83+section, not per channel.
84+
85+## Agents in channels
86+
87+- An agent is added to a channel like a person, with the agent's own
88+ credentials, guardrails and audit log. Private channels exclude agents
89+ unless added by name.
90+- A mention in a pull request's thread steers that pull request's agent
91+ (`agent_messages`). A mention anywhere else starts an agent run whose
92+ replies post in the thread.
93+- Asking a person for approval (merge past branch protection, deploy to
94+ production) posts a card with the actions on it, and the same item lands
95+ in the person's inbox. Acting in either place resolves both.
96+
97+## Build order
98+
99+1. **Contracts.** Channel, message and card types in `packages/contracts`
100+ and `crates/contracts`; the RPC methods; the new event types.
101+2. **Channels.** `services/chat`, its migrations, a Durable Object per
102+ channel, and `deploy/stack.jsonc` entries. Create, join, post, edit,
103+ threads, reactions, read state.
104+3. **Chat mode.** The rail in `shell.tsx`; the Chat sidebar with starred,
105+ sections, filters and browse; the channel page; the composer with
106+ mentions. Code mode is unchanged apart from the rail.
107+4. **Mentions to the inbox.** `chat.message.created` and inbox rows with
108+ reason `mention`.
109+5. **Project links and cards.** Link a channel to a project; the events
110+ subscriber; cards for pull requests, issues, checks and deploys; the
111+ project chat dock in Code mode.
112+6. **One timeline.** A card's thread is the issue's or pull request's
113+ timeline, both ways, with "also send to channel".
114+7. **Agents.** Agents as members, steering by mention, approval cards,
115+ direct messages with agents.
116+8. **Scale.** Team sections, computed active-project section, muting,
117+ browse, search.
118+
119+Steps 1 to 4 are a usable chat; 5 and 6 are what no chat app can do.
120+
121+## Open questions
122+
123+- Must every channel belong to a project or team? Requiring one makes the
124+ sidebar's sections better and orphans fewer channels.
125+- Do agents get their own mode, or only appear as direct messages?
126+- Retention and export for workspaces that need it.
127+- Does a self-hosted install ship chat, or is it hosted only at first?