···7575### 2.5 Conversation Key Rules
7676Implemented constructors:
7777- Telegram chat: `tg:<chat_id>`
7878-- MAEP peer: `maep:<peer_id>`
7978- Slack channel: `slack:<team_id>:<channel_id>`
8079- Discord channel: `discord:<channel_id>`
8180···9695- Telegram:
9796 - inbound: `internal/bus/adapters/telegram/inbound.go`
9897 - delivery: `internal/bus/adapters/telegram/delivery.go`
9999-- MAEP:
100100- - inbound: `internal/bus/adapters/maep/inbound.go`
101101- - delivery: `internal/bus/adapters/maep/delivery.go`
10298- Slack:
10399 - inbound: `internal/bus/adapters/slack/inbound.go`
104100 - delivery: `internal/bus/adapters/slack/delivery.go`
···109105- starts inproc bus
110106- subscribes `AllTopics()` with one dispatcher by `direction + channel`
111107- Telegram poll inbound path: Telegram inbound adapter -> bus -> handler -> worker queue
112112-- MAEP inbound path under `--with-maep`: `OnDataPush -> MAEP inbound adapter -> bus -> handler`
113108- business outbound messages (task output, task failures, file-download failures, plan updates) are sent through bus outbound
114109- operational/admin messages (for example `/help`, `/mem`, initialization/system notices) may still use direct send
115110···119114- inbound path: Slack Socket Mode event -> Slack inbound adapter -> bus -> handler -> per-conversation worker
120115- task output and error replies are published as outbound bus messages, then delivered by Slack delivery adapter
121116122122-`mistermorph maep serve`:
123123-- starts inproc bus
124124-- `OnDataPush -> MAEP inbound adapter -> bus -> handler`
125125-- handler prints events and optionally syncs contacts
126126-127117`internal/contactsruntime/sender.go`:
128118- `NewRoutingSender` starts inproc bus and delivery adapters internally
129129-- `Send(...)` routes to Telegram / Slack / MAEP, then publishes outbound `BusMessage`
119119+- `Send(...)` routes to Telegram / Slack, then publishes outbound `BusMessage`
130120- `publishAndAwait(...)` uses a pending map for synchronous delivery result waiting
131121- fail-fast: missing `idempotency_key` is an immediate error
132122···172162173163```text
174164Telegram poll/getUpdates ----\
175175-Slack Socket Mode ------------+--> inbound adapters (telegram/slack/maep)
176176-MAEP OnDataPush -------------/ |
165165+Slack Socket Mode ------------+--> inbound adapters (telegram/slack)
177166 v
178167 +----------------------+
179168 | inproc bus runtime |
···188177 | |
189178 v v
190179 run task / agent delivery adapters
191191- | (telegram / slack / maep)
180180+ | (telegram / slack)
192181 +-------------------------+-------------------+
193182 |
194183 v
195195- Telegram / Slack / MAEP send
184184+ Telegram / Slack send
196185```
197186198187### 3.2 Shared Inbound Path (`InboundFlow`)
···221210## 4) Design Evaluation (Current State)
222211223212### 4.1 Why this is reasonable now
224224-- Minimal viable path is complete: Telegram / Slack / MAEP inbound/outbound paths are unified through bus.
213213+- Minimal viable path is complete: Telegram / Slack inbound/outbound paths are unified through bus.
225214- Ordering is explicit and enforceable per `conversation_key`.
226215- Backpressure is bounded and observable via typed error (`QUEUE_FULL`).
227216- Idempotency is explicit via inbox/outbox keyed records.
···236225## 5) Delivery Status
237226238227### 5.1 Completed
239239-- Telegram/MAEP inbound adapters
240240-- Telegram/MAEP delivery adapters
228228+- Telegram inbound/delivery adapters
241229- Slack inbound/delivery adapters
242230- outbound bus migration in `contactsruntime sender`
243231- Slack runtime bus path (`mistermorph slack`) with inbound publish and outbound delivery
244232- main-path test coverage expansion
245233- migration of Telegram business direct-send paths to bus outbound (admin paths excluded)
246234- typed error code propagation in call-site logging
247247-- cross-channel regression: Telegram inbound -> MAEP outbound
248235249236### 5.2 Verified test set
250237Verified locally on `2026-02-17`:
251238- `go test ./internal/bus/...`
252239- `go test ./internal/bus/adapters/...`
253240- `go test ./internal/contactsruntime/... ./contacts/...`
254254-- `go test ./cmd/mistermorph/telegramcmd ./cmd/mistermorph/maepcmd ./cmd/mistermorph/slackcmd`
241241+- `go test ./cmd/mistermorph/telegramcmd ./cmd/mistermorph/slackcmd`
255242- `go test ./...`
256243257244## 6) Backlog (Separated from Current State)
+14-17
docs/bus_impl.md
···1111In scope:
1212- `internal/bus` runtime, validation, and error model
1313- `internal/bus/adapters/*` inbound and delivery adapters
1414-- Bus wiring in `cmd/mistermorph/telegramcmd` and `cmd/mistermorph/maepcmd`
1414+- Bus wiring in `cmd/mistermorph/telegramcmd` and `cmd/mistermorph/slackcmd`
1515- Bus inbox/outbox state in `contacts/*`
1616- Outbound bus path in `internal/contactsruntime/sender.go`
17171818Out of scope:
1919- Multi-channel architecture roadmap and product-level planning (see `docs/bus.md`)
2020-- MAEP protocol specification details (see `docs/maep.md`)
21202221## 2) Bus Runtime (`internal/bus`)
2322···6564- Generic constructor: `BuildConversationKey(channel, id)`.
6665- Implemented specialized constructors:
6766 - `BuildTelegramChatConversationKey`
6868- - `BuildMAEPPeerConversationKey`
6967 - `BuildSlackChannelConversationKey`
7068 - `BuildDiscordChannelConversationKey`
7169- `tg:@<username>` is not a Telegram delivery conversation key (delivery requires numeric `tg:<chat_id>`).
···8482- Delivery (`telegram/delivery.go`): consumes `outbound/telegram` and sends text via resolved target.
8583- Idempotency key strategy: `idempotency.MessageEnvelopeKey(message_id)`.
86848787-### 3.3 MAEP Adapters
8888-- Inbound (`maep/inbound.go`): maps `maep.DataPushEvent` to `BusMessage` (`inbound/maep`) and reuses `InboundFlow`.
8989-- Delivery (`maep/delivery.go`): consumes `outbound/maep` and calls `Node.PushData`.
8585+### 3.3 Slack Adapters
8686+- Inbound (`slack/inbound.go`): maps Slack Socket Mode events to `BusMessage`.
8787+- Delivery (`slack/delivery.go`): consumes `outbound/slack` and sends message text to target channel/thread.
90889189### 3.4 Demo Adapter
9290`adapters/demo` remains as a template validation path built on `InboundFlow`.
···9896- Subscribes `AllTopics()` and dispatches by `direction + channel`.
9997- Inbound paths:
10098 - Telegram polling -> Telegram inbound adapter -> bus -> handler -> worker queue
101101- - `--with-maep`: MAEP `OnDataPush` -> MAEP inbound adapter -> bus
10299- Outbound paths:
103100 - `outbound/telegram` -> Telegram delivery adapter
104104- - `outbound/maep` -> MAEP delivery adapter
105101- Business outputs (task output, task failure, file-download failure, plan updates) are on bus outbound.
106102- Operational/admin responses (`/help`, `/mem`, bootstrap guidance, etc.) may still use direct send.
107103108108-### 4.2 `mistermorph maep serve`
109109-- Starts inproc bus and subscribes `AllTopics()`.
110110-- MAEP `OnDataPush` is normalized through MAEP inbound adapter -> bus.
111111-- Handler projects bus message back to event shape for CLI output and optional contacts sync.
104104+### 4.2 `mistermorph slack`
105105+- Starts inproc bus using `bus.max_inflight`.
106106+- Subscribes `AllTopics()` and dispatches by `direction + channel`.
107107+- Inbound path: Slack Socket Mode events -> Slack inbound adapter -> bus -> handler -> worker queue.
108108+- Outbound path: `outbound/slack` -> Slack delivery adapter.
112109113110### 4.3 `internal/contactsruntime/sender.go`
114111- `RoutingSender` starts inproc bus and both delivery adapters internally.
···158155## 7) Completion Status
159156Implemented:
160157- Bus runtime semantics (ordering, backpressure, topology freeze, typed errors)
161161-- Telegram and MAEP inbound adapters
162162-- Telegram and MAEP delivery adapters
163163-- Bus wiring in Telegram and MAEP command paths
158158+- Telegram and Slack inbound adapters
159159+- Telegram and Slack delivery adapters
160160+- Bus wiring in Telegram and Slack command paths
164161- Outbound publish path in `contactsruntime` sender
165162- Contacts outbox state machine and idempotent send flow
166163- Typed error code propagation in caller-side logs (`bus_error_code`)
167167-- Cross-channel regression path: Telegram inbound -> MAEP outbound
164164+- Cross-channel regression path: Telegram inbound -> Slack outbound
168165169166Not implemented yet:
170170-- Slack/Discord adapter integration into main runtime path
167167+- Discord adapter integration into main runtime path
171168- External bus backend (for example Redis Streams)
172169- Retry / DLQ workers
+2-2
docs/tools.md
···134134- Requires an LLM client and model; returns an error if not bound.
135135- `add` uses a "param extraction + LLM insertion" flow: `people` comes from tool params, then the LLM inserts `name (ref_id)` based on `content`, raw user input, and runtime context.
136136- `chat_id` currently accepts only `tg:<chat-id>` (signed int64, non-zero).
137137-- `add` only accepts reference IDs in this set: `tg:<int64>`, `tg:@<username>`, `maep:<peer_id>`, `slack:<channel_id>`, `discord:<channel_id>`.
137137+- `add` only accepts reference IDs in this set: `tg:<int64>`, `tg:@<username>`, `slack:<channel_id>`, `discord:<channel_id>`.
138138- Reference IDs in `add` must exist in contact snapshot `reachable_ids`.
139139- If some people in `add` cannot be mapped to reference IDs, the tool does not fail; it falls back to writing raw `content` and appends `reference_unresolved_write_raw` in `warnings`.
140140- `complete` relies only on LLM semantic matching (no programmatic fallback); ambiguous matches return an error directly.
···164164165165## `contacts_send`
166166167167-Purpose: send a single message to one contact (auto-routed via MAEP/Telegram).
167167+Purpose: send a single message to one contact (auto-routed via Telegram/Slack).
168168169169Contact profile maintenance:
170170