docs/plans/2026-07-18-observed-channel-group-names.md
For agentic workers: Execute each task test-first and keep the change limited to inbound metadata already supplied by the platform.
Goal: Return human-readable observed group labels when an accepted inbound callback already contains a group name, while retaining complete platform IDs and the existing ID fallback.
Architecture: Channel adapters copy an optional inbound group name into Envelope.chatName. ChannelBase sanitizes that observation and writes it as group.label; the existing workspace store handles bounds, refresh, freshness, and graph derivation without a schema change. No adapter performs additional network requests.
chatId as the routing, session, deduplication, and graph identity key.chatName only for groups[].label on group messages.Files: packages/channels/base/src/types.ts, packages/channels/base/src/ChannelBase.test.ts, packages/channels/base/src/ChannelBase.ts
chatName becomes group.label, malformed or empty names fall back to the complete chatId, and direct messages ignore chatName.cd packages/channels/base && npx vitest run src/ChannelBase.test.ts and confirm the new assertions fail for the missing contract.chatName?: string to Envelope.chatId when unusable.Files: packages/channels/dingtalk/src/DingtalkAdapter.test.ts, packages/channels/dingtalk/src/DingtalkAdapter.ts
conversationTitle and assert the processed envelope contains chatName while preserving chatId.cd packages/channels/dingtalk && npx vitest run src/DingtalkAdapter.test.ts and confirm the new assertion fails.conversationTitle to the raw inbound type, validate it as a string, and place it on the group envelope.Files: packages/channels/telegram/src/TelegramAdapter.test.ts, packages/channels/telegram/src/TelegramAdapter.ts
chat.title values become chatName, while a private chat does not expose a group name.cd packages/channels/telegram && npx vitest run src/TelegramAdapter.test.ts and confirm the new assertions fail.title and copy it only for group or supergroup envelopes.Files: docs/design/2026-07-17-observed-channel-delivery-targets.md, docs/users/features/channels/overview.md
npm run lint && npm run typecheck && npm run build.feat/channel-observed-group-names, and open a stacked ready-for-review PR that declares its dependency on #7109 and links #7154.conversationTitle payload, use #7109's live DingTalk transport result as the transport precondition, and record Feishu as a negative schema/fallback check rather than making an API request.