Skip to content

Handoff: sync the dsh-im fork and add a first WhatsApp DM tracer #3676

Open

Description

@DoodleBears

Handoff: 同步 dsh-im fork,并接入第一个 WhatsApp DM tracer

Part of #48. 这是一份 handoff / 协作 hub,不是已经领取的实现任务,也不代表 WhatsApp 已获准作为公开产品能力。

目标读者:第一次给 BotHarness 贡献、还没有 clone/fork 过本仓库的工程师。你不需要先理解整个架构;按下面的顺序做,每一步都有可运行的验收点。


0. 一句话

先把 BotHarness/dsh-im 这个 Provider fork 同步到上游 xmanrui/dsh-im,再在 BotHarness/DeepSeekBot(Tobs)主项目里,用同一个 checked Provider/Consumer 边界接入 WhatsApp。第一个切片只做:

扫码绑定的 WhatsApp 账号,在 self-chat / paired-owner DM 里收到一条文字 → canonical Source Event + Bot Inbox → 真实模型 → 用同一个账号在原会话回复。

不要一上来做群、媒体、语音、typing 或主动发送。它们各自是后续 tracer。


1. 为什么必须先同步 fork

两个仓库的分工:

层 仓库 负责什么
Provider / 原生连接 BotHarness/dsh-im WhatsApp Web linked-device 连接、账号身份、收件、发送、checked capability
产品权威 / UI / CLI BotHarness/DeepSeekBot Binding、Grant、Source Event、Inbox Admission、Channel 投递、Outbox、设置页、CLI、文档
发布产物 BotHarness/DeepSeekBot + release workflow 把 fork 打成 @botharness/im-provider,独立 pin、独立验收;不等于上游发布

dsh-im 上游已经有一个通用 WhatsApp channel,但它目前是 standalone dsh-im Session / 自带 Harness bridge 的形态。BotHarness 需要的是可检查的 Provider/Consumer 契约:账号 fingerprint、独占收件、精确来源证明、发送前 fence、原生回执。这个契约在 fork 里已经给 Lark / Slack / Discord / WeChat / QQ 做过,WhatsApp 还没有。

如果先改主项目、后补 Provider,结果会是一个能显示 WhatsApp 但收不到、也发不出的 UI。因此顺序是:fork 同步 → Provider checked consumer → 主项目 tracer。


2. 当前事实(2026-11-07 核对;开始前请重新 fetch)

  • 上游 xmanrui/dsh-im 已有 WhatsApp channel:
    • src/channels/whatsapp/:Baileys / WhatsApp Web linked-device、QR provisioning、self-chat 默认、可选联系人白名单 / open 模式、群消息显式触发、图片/文件/音视频、编辑式流式回复。
    • plugin-src/host/channels/whatsapp/:Host 侧 RPC、production runtime、delivery adapter 已把 whatsapp 列入支持 channel。
    • 但它没有 external-consumer.mjs,也没有 checked consumer 的 describeDeliveryAccount / consumeInbound / qualifyReplyChecked / replyChecked。所以 BotHarness 目前看不到一个“可绑定的 WhatsApp 账号”。
  • BotHarness/dsh-im 是 BotHarness 维护的 Provider fork:
    • 它保留上游 channel,同时叠加 checked Provider/Consumer 契约;npm run build 生成 lib/index.js,BotHarness 按 lib + plugin-src + src 的 runtime digest 固定版本。
    • 截至核对时:fork origin/main 为 bde1cace,比上游 fc2ceab2 ahead 168 / behind 338。本地 clone 可能更旧,先 fetch 再判断。
    • BotHarness 的开发 pin 是 scripts/dev-im-provider.mjs 里的 beaed4a6,不是 fork tip;产品 artifact pin 又是另一套文件。不要把三者混为一个“版本”。
  • BotHarness/DeepSeekBot 当前只识别 5 个 IM 平台:
    • packages/core/src/messaging/dsh-im.ts 的 createDshImProvider(..., platform) 与 inbound schema
    • packages/core/src/plugin.ts 的 ['feishu', 'slack', 'discord', 'weixin', 'qq'] 循环
    • 客户端设置页、默认值、CLI、数据库 CHECK (platform IN (...))、文档与 feature map 都只覆盖这 5 个
  • 仓库里目前没有 WhatsApp 的既有 issue/claim;这是第一条。

注意:不要把 WhatsApp 说成“官方 WhatsApp Business API”。现有 dsh-im 实现是 WhatsApp Web linked device(Baileys),链接的是 owner 自己的 WhatsApp 账号。它有明确的账号封禁、隐私和 ToS 风险。产品是否允许公开支持它,必须由 maintainer 先决定;本 handoff 只按“开发 tracer + 专用 QA 账号”设计。


3. 硬规则(请先读,避免白做)

  1. 一个 PR 只做一个可运行的切片。 不要把 fork 同步、Provider、主项目 UI、群/媒体混在一个 PR。
  2. 不要 force-push / rebase 已发布的 fork main。 BotHarness 按 SHA + runtime digest pin;重写历史会让已有 Profile 无法复现。同步用 merge commit。
  3. 不要改产品 Provider pin,不要发布 npm,不要动生产 Profile。 开发 pin 和产品 pin 是两回事。
  4. 不要提交任何 WhatsApp 凭据、auth state、QR、手机号、JID、聊天正文或未脱敏截图。 使用专用 QA 手机/账号,不要用个人主号。
  5. 一个账号只能有一个 receiver。 复用 exclusive-inbound-consumers,不要起第二个 standalone dsh-im Session,也不要让两个 Host 同时收同一账号。
  6. 没有原生证据就不要声明能力。 Baileys 返回的 message key 不等于“服务端已送达/已读”;不确定时只暴露 reply-text-checked / reply-fence-checked,不要加 reply-receipt-checked。
  7. 不要全局替换 weixin 特判。 WhatsApp 和微信的会话语义不同(linked device、群触发、JID/LID、媒体编码)。逐个位置判断。
  8. 不要把 WhatsApp 加进公开文档/安装指南后又说“已支持”。 先有真实验收,再升级 qualification ledger。

4. Workstream A — 把 fork 跟到上游

A0. Clone / remotes

如果直接 clone BotHarness fork:

git clone https://github.com/BotHarness/dsh-im.git
cd dsh-im
git remote add upstream https://github.com/xmanrui/dsh-im.git
git fetch --all --prune

如果你没有 fork 写权限,先 fork BotHarness/dsh-im 到自己的账号,再:

git clone https://github.com/<you>/dsh-im.git
cd dsh-im
git remote add upstream https://github.com/xmanrui/dsh-im.git
git remote add botharness https://github.com/BotHarness/dsh-im.git
git fetch --all --prune

DoodleBears/dsh-im 是旧 URL,会 redirect 到 BotHarness/dsh-im;新文档/命令请用新 URL。

A1. 建同步分支并 merge 上游

git switch -c codex/whatsapp-fork-sync-20261107 botharness/main
# 或:git switch -c codex/whatsapp-fork-sync-20261107 origin/main
git merge upstream/main

不要用 GitHub 网页的 “Sync fork” 按钮代替本地 merge:冲突需要在本地解决,而且你需要保留 fork-only 的 checked commits。

A2. 解决冲突

高风险文件(上游和 fork 都改过):

  • plugin-src/host/index.mjs
  • plugin-src/host/delivery-adapter.mjs
  • plugin-src/host/delivery-service.mjs
  • plugin-src/host/app-setup.mjs
  • src/channels/shared/*(尤其 exclusive-inbound-consumers.mjs、harness-*、session-*)
  • 各 checked channel 的 external-consumer.mjs / *-controller.mjs / *-runtime.mjs
  • package.json / package-lock.json(上游可能改 DSH/SDK 兼容范围)
  • lib/index.js、lib/client.js(生成物;不要手工 merge,解决源码后重新 build)

判断原则:

  • fork-only 的 checked capabilities 不能因为“上游没有”就删掉。
  • 上游的新 channel 行为不能因为“fork 有 checked 版本”就整体丢弃。
  • 两边都要时,用 capability / consumerMode / 显式分支保留两种行为,不要用静默 fallback。
  • 不确定的冲突先在 PR 描述里列出来,不要猜。

A3. 构建与测试

node --version          # 需要 >= 22.19(见 package.json engines)
npm ci
npm run build
npm test
npm run check           # build + test + verify-package
git status --short      # 应看到重新生成的 lib/*.js

Windows 上用 PowerShell 直接跑即可;不要新建 .ps1/.cmd/.bat。

A4. 给 fork 开 PR

  • Base:BotHarness/dsh-im:main
  • Head:你的 codex/whatsapp-fork-sync-...
  • 描述里写:上游 SHA、merge commit、冲突文件与解决理由、npm test / npm run check 的实际结果、runtime 文件数变化。
  • 不要在这个 PR 里改 BotHarness 主项目,也不要改产品 pin。

A5. 同步 BotHarness 开发 pin(单独 PR)

合并后,在 BotHarness/DeepSeekBot 单独开一个 PR:

  • scripts/dev-im-provider.mjs:source、spec(用 github:BotHarness/dsh-im#<sha>)、runtimeFiles、runtimeSha256
  • 用导出的 providerRuntimeDigest 计算 digest,例如:
node --input-type=module -e "import { providerRuntimeDigest } from './scripts/dev-im-provider.mjs'; console.log(providerRuntimeDigest(process.argv[1]))" <path-to-installed-@xmanrui/dsh-im>
  • 用 node scripts/dev-instance.mjs --home <tmp> --port <n> --im-provider 启动一次,确认 helper 的 runtime 校验通过。
  • 不要同时改 scripts/published-product-provider.json / scripts/product-artifacts.mjs / release workflow。产品 pin 要等真实验收后单独走 release 流程。

A6. 如果上游有可复用的通用修复

upstream contribution 是加分项,不是前置条件。可以把通用的 Host/Client 修复单独提到 xmanrui/dsh-im;BotHarness fork 仍然按自己的 checked 契约维护。不要在同一个 PR 里同时做“上游 PR + fork 同步 + WhatsApp 功能”。


5. Workstream B — 第一个 WhatsApp tracer

B0. 先确认(不要跳过)

在写代码前,先在这个 issue 里让 maintainer 确认四件事:

  1. 连接方式:继续用现有 Baileys / WhatsApp Web linked device,还是改走官方 WhatsApp Business Cloud API?
    • 如果选官方 Cloud API,Provider 层要重新设计(webhook、Meta App、phone number ID、模板消息),本 handoff 的 B1 不适用。
  2. 首个切片:self-chat / paired-owner DM 的文字收发,是否就是你要的 tracer?
  3. QA 账号:谁提供专用手机/WhatsApp 账号?谁授权扫码链接?不要用个人主号。
  4. 公开边界:这个切片是否只作为开发 tracer,不进入产品 pin、不发布文档?如果是,验收后再讨论产品化。

如果这四点没有确认,先不要动 B2 之后的代码。

B1. dsh-im:补 checked WhatsApp consumer

参考实现(按接近程度排序):

  • src/channels/weixin/external-consumer.mjs + weixin-controller.mjs + weixin-runtime.mjs:paired-owner DM、source proof、checked reply、typing、文件/图片/语音的扩展方式。
  • src/channels/qq/external-consumer.mjs:reply-only group text 的 capability 组合与 fence,适合“首个切片只回复、不主动发送”。
  • src/channels/shared/exclusive-inbound-consumers.mjs:独占 consumer。
  • plugin-src/host/channels/weixin/production.mjs:如何把 controller 接到 createDeliveryAdapter。

建议的新增/修改:

  • src/channels/whatsapp/external-consumer.mjs(新)
    • verifiedWhatsappAccount(config):从已链接账号的稳定身份派生 fingerprint;relink / 换号必须改变 fingerprint。不要把 auth keys、原始 JID、手机号放进公开 DTO。
    • normalizeWhatsappExternalText(message, ...):首个切片只接受 self-chat 的纯文字 DM。精确使用 Baileys key.id 作为 eventId / messageId;conversation.kind = 'dm';mentions = [];mentionedAccount = false;replay = { kind: 'provider-redelivery', resumeCursor: false, gapPossible: true }。
    • checkedWhatsappRoute(route, account, source):把公开的 { messageId, conversationId, actorId } 绑定到进程内私有 source proof(原始 message key、remoteJid、participant、时间、过期时间)。不创建第二份 transcript。
    • 明确拒绝:group / status@broadcast / newsletter / fromMe 但非 self-chat / 空文本 / 超长文本 / 无法验证的账号。
  • src/channels/whatsapp/config-store.mjs
    • 增加 consumerMode: 'standalone-session' | 'external-consumer' 的持久化与校验;默认 standalone,BotHarness 注册时切到 external-consumer。
  • src/channels/whatsapp/whatsapp-controller.mjs
    • describeDeliveryAccount(botId):返回 { version: 1, botId, channel: 'whatsapp', account: { fingerprint, name? }, connected, capabilities: [...] }。
    • consumeInbound(botId, { expectedFingerprint, onEvent, signal }):注册独占 consumer,校验 fingerprint,持久化 consumerMode,返回 dispose。只在 onEvent 成功 commit 后 ack;不要另起 Session。
    • qualifyReplyChecked(botId, route, options)、replyChecked(botId, route, text, options):每次都用当前账号 + source proof 重新校验,发送前调用 beforeSend fence;用 Baileys 在原始 chat 发送(带 quoted message key)。返回值只声明真实拿到的结果。
    • 首个切片不要实现 postConversationChecked / listReachableConversations / beginTypingChecked / historyChecked,除非你已经能证明它们;没有它们时 proactive / typing / history 自然不可用。
  • src/channels/whatsapp/whatsapp-runtime.mjs
    • external-consumer 模式下不要创建 WhatsappHarnessBridge,不要走 standalone Session;只把允许的入站事件交给 consumer。
    • 增加有界、进程内、按精确 message ID 索引的 source proof;重启/relink/注销时清空;不要持久化正文。
    • 保留已有的 RecentWhatsappOutboundIds 做自己 Echo 抑制,但不要把 Echo 当作发送回执。
  • src/channels/whatsapp/state-store.mjs
    • 只在需要时保存最小状态;不要把 Baileys auth、消息正文、JID 列表写进可公开的状态。
  • plugin-src/host/app-setup.mjs
    • 当前只注册 feishu / weixin,且 QR 分支只认 weixin + verificationUrl;WhatsApp controller 的 startProvisioning 返回的是 qrValue。
    • 需要把 QR 分支泛化为 channel-specific adapter:describe('whatsapp') -> { kind: 'qr' },setup.start 调 startProvisioning({ consumerMode: 'external-consumer', signal }),把 qrValue 渲染成 qrDataUrl(或让 controller 返回可渲染的验证 URL),setup.poll / setup.cancel 复用现有生命周期。
    • QR 不得写日志、不得在错误信息里回显。
  • plugin-src/host/channels/whatsapp/production.mjs
    • createDeliveryAdapter 已经是通用的,不需要新增 adapter 类型;确认 controller 暴露了上面的方法即可。
  • 测试
    • test/channels/whatsapp/external-consumer.test.mjs(新增)
    • test/channels/whatsapp/production.test.mjs、whatsapp.test.mjs 补充 external-consumer / QR / reply 路径
    • 覆盖:self-chat 文字、群消息被拒、非白名单 DM 被拒、错误 fingerprint、重复投递、过期 source、relink 后旧 route 失效、发送前 fence 取消、未知结果不重试、无凭据/正文日志。

Capability 组合建议(reply-only DM)

exclusive-text-consumer
reply-text-checked
reply-context-checked
reply-fence-checked

只有在你能用真实 Baileys 返回值和原生观察证明稳定 message ID 时,才加 reply-receipt-checked。首个切片不要加 proactive-*、source-*、source-quote-*、typing-*。

主项目的 createDshImProvider 目前对“没有 proactive-text-checked 的 reply-only Provider”只给 QQ 开了口子;WhatsApp 需要显式把同样的 reply-only 能力组合加进判断,或者明确要求 proactive-text-checked。两条路都要有测试,不要靠“平台名碰巧通过”。

B2. BotHarness:平台接入

先用最近一次 QQ 平台接入作为模板:

git show --stat 235884fb1   # QQ checked group text 的首个平台接入
git show --stat 018acb854   # QQ defaults / private message 的后续修正

需要动的核心文件:

  • packages/core/src/messaging/provider.ts
    • MessagingInboundEvent.channel 加 'whatsapp'
    • MessagingSetup.platform 加 'whatsapp'
  • packages/core/src/messaging/dsh-im.ts
    • createDshImProvider 的 platform union
    • inboundSchema 的 channel enum
    • setup 分支:platform === 'whatsapp' 时 kind: 'qr',允许 describeSetup('whatsapp')
    • targets():首个切片对 kind === 'user' 的 WhatsApp target 给 receiveScope: { kind: 'dm', conversationId: target.route.jid }
    • capability 判断:reply-only 分支、postSupported、typingSupported 只在真实能力存在时为 true
  • packages/core/src/plugin.ts
    • 平台循环加入 'whatsapp'
  • packages/core/src/messaging/defaults.ts
    • messagingDefaultsPlatform 加 'whatsapp'
    • 默认 collection/wake 要显式决定。如果首个切片只有 self-chat DM,可以按 WeChat 的 all / immediate 形状;但 WhatsApp 未来会有群,平台级默认值同时作用于群和 DM,先和 maintainer 确认是否需要按会话类型分开。不要无脑复制 weixin 的 typing 特判。
  • packages/core/src/database/schema-plan.ts
    • 当前最新 migration generation 是 105;新增一个 >105 的 migration,按 generation 69(WeChat defaults)的做法重建 messaging_default_revisions,把 whatsapp 加入 CHECK (platform IN (...))。
    • 不要改历史 migration;补 operational-database.test.ts 的升级/新库用例。
  • packages/core/src/bots/cli-messaging.ts
    • PLATFORMS 加 'whatsapp'
  • packages/core/src/bots/cli-im-authorization.ts
    • Platform union、im-authorize 的目标列表、project() 的 channel 校验、QR 的 next 文案
    • im-apps 能发现 dsh-im/whatsapp;im-authorize whatsapp 可启动 QR;im-verify 仍然只属于微信(WhatsApp 没有手机验证码步骤),im-credentials 仍然只属于 Feishu。
  • packages/core/src/messaging/im-commands.ts
    • 决定 WhatsApp owner DM 是否支持 /commands。如果支持,扩展现有 WeChat 特判;如果不支持,明确返回 Web 指引。不要默认放行。
  • packages/core/src/messaging/inbound.ts / outbound.ts / channel-bridge.ts / identity.ts / retained-context.ts / bridge/methods.ts
    • 搜索所有 weixin 特判,逐个判断 WhatsApp 是否同语义。retained-context 是微信本地上下文,不要直接套到 WhatsApp;CONNECTOR_TYPES、DM Grant、channel-bridge 只在你确实支持群/DM 连接器时加。
  • 客户端
    • packages/client/src/client/provider-app-setup.ts:platform union 加 whatsapp
    • create-app-form.tsx:QR 状态 / 文案 / 提交
    • external-identity-list.tsx:平台行、DM-only 提示、教程链接
    • messaging-defaults-settings.tsx:平台选项与说明
    • bridge-source-label.ts:whatsapp 标签
    • bridge.ts:事件 channel guard
    • messaging-grant.tsx / channel-bridge-list.tsx:只有 DM/群语义确认后才加对应文案
    • locale.ts:中英文 im.platform.whatsapp、appSetup.whatsapp、identity.tutorial.whatsapp、DM 收件提示、默认值说明;两套语言必须同时改
  • 文档 / release
    • docs/whatsapp-connection.md + docs/whatsapp-connection.zh.md(真实验收后再写“已支持”)
    • scripts/sync-docs.mjs 注册两个版本
    • docs/dev/guides/im-provider-integration.md + .zh.md 的 qualification ledger(先写“开发来源 / 未产品化”)
    • docs/bot-cli.md + .zh.md 的 im-authorize whatsapp
    • 架构文档 / 新 ADR:linked-device、非官方自动化、账号风险、产品边界
    • changes/<issue>-whatsapp.md(不要直接改 CHANGELOG.md / CHANGELOG.zh.md),跑 pnpm changelog:check
  • feature map
    • 如果 UI 路径发生变化,更新 .agents/skills/verify-deepseekbot/features/README.md 与对应 feature 文件,跑 node scripts/check-feature-map.mjs
  • 测试
    • packages/core/test/messaging-whatsapp.test.ts(DM intake / reply / duplicate / wrong account / no retry)
    • packages/core/test/dsh-im-unsupported.test.ts(reply-only capability 组合)
    • packages/core/test/messaging-default-traffic.test.ts、operational-database.test.ts、bot-im-cli.test.ts
    • client 的 provider-app-setup.test.ts、external-identity-list.test.ts
    • 跑 pnpm test、pnpm lint、pnpm typecheck、pnpm format:check

B3. 验收(必须真实)

自动化测试只能证明契约;不能证明 WhatsApp 客户端真的收到回复。

  1. Provider 合同:dsh-im npm run check 全过;新增消费/回复/fence/relink 回归。
  2. 隔离 Host:更新开发 pin 后,用 node scripts/dev-instance.mjs --home <tmp> --port <n> --im-provider 启动;helper 必须先通过 runtime digest 校验。确认一个真实模型 DM 能回复(先排除模型/凭据问题)。
  3. 扫码链接:用专用 QA 手机/账号扫码;确认绑定行、账号 fingerprint、连接状态。
  4. 首个真实 tracer:
    • 在 self-chat 发一条唯一标记文字;
    • 确认恰好一条 canonical Source Event、一条 Inbox Admission;
    • 真实模型产生一次 bridge_reply;
    • 在原 self-chat 看到同一个账号的回复;
    • Outbox 有记录的 receipt / unknown 状态,未自动重试。
  5. 边界回归:重复投递、错误账号、relink/注销后旧 route 失效、发送前撤销 Binding/Grant、未知发送结果不重试。
  6. 证据:截图/录屏只保留脱敏后的设置页、绑定行、source details、原生回复;二维码、手机号、JID、聊天正文必须裁掉或打码。按 verify-deepseekbot 技能留 ARIA/console/截图;Human QA 与自动化分开记录。
  7. 文档:先写“开发 tracer / 未产品化”,不要升级公开 capability 表;产品 pin 和发布是后续独立决定。

B4. 第一个 PR 的范围建议

按 tracer bullets 拆:

  • PR 1(dsh-im):fork 同步上游,保留 checked 契约。
  • PR 2(dsh-im):WhatsApp checked DM text consumer + QR setup + 测试;不碰主项目。
  • PR 3(DeepSeekBot):主项目接入一个 DM text tracer(core + client + CLI + docs + 开发 pin);不改产品 pin。
  • PR 4+(后续):群消息、图片/文件、语音、typing、主动发送;每个都单独 tracer、单独验收。

PR 1 可以先做,PR 2/3 依赖 PR 1 合并后的 fork SHA。不要把它们压成一个超大 PR。


6. 第一个星期可以这样走

  1. 读下面“阅读清单”的前四项;在这个 issue 下留言,说明你的时区、是否有专用 WhatsApp QA 账号、想先做哪一步。
  2. 等 maintainer 确认 B0 的四个问题;不要先写 UI。
  3. 做 Workstream A:同步 fork,npm run check 通过,开 PR。
  4. 做 B1:WhatsApp checked DM text + 单测;用 dsh-im 自己的测试证明契约。
  5. 做 B2/B3 的最小垂直切片:一个 DM 文字 → Inbox → 模型 → 原生回复;先跑通,再补 UI 文案/教程/文档。
  6. 把真实证据和未覆盖项写进 PR;等 Human QA 后再讨论群/媒体。

如果时间有限,只完成第 3 步也是有价值的交付:fork 同步本身就是当前最大的阻塞项。


7. 阅读清单

先读:

按需读:


8. 如何领取

在这个 issue 下留言,包含:

  • 你的 GitHub handle 和大致时区;
  • 是否有专用 WhatsApp QA 手机/账号(没有也可以先做 Workstream A);
  • 你想先做 A、B1 还是 B2/B3;
  • 相关经验(Baileys、DSH plugin、BotHarness IM、TypeScript/React 任一即可)。

Maintainer 确认后,再按 docs/agents/issue-tracker.md 的 claim 约定标记 in-progress / agent:active(如果适用)。不要在确认前开始改代码,也不要用个人 WhatsApp 主号做测试。

PR 里用 Refs #<this>,不要用 Closes 关闭整个 handoff;两个 workstream 都落地并验收后再关闭。


9. 需要 maintainer 先回答的问题

  1. 我们接受 Baileys / WhatsApp Web linked device 作为开发 tracer 吗?如果只接受官方 WhatsApp Business Cloud API,请明确,B1 需要重写。
  2. 首个切片是否就是 self-chat / paired-owner DM 文字?还是希望先做群 @?
  3. 谁提供并授权专用 QA 手机/账号?扫码链接的同意窗口由谁执行?
  4. WhatsApp 在产品里是否只作为“开发来源 / 未发布 capability”,直到真实验收?产品 pin 和公开文档的升级条件是什么?
  5. 平台默认值怎么处理:DM 要 all/immediate,未来群要 mentions/digest,现有 messaging_default_revisions 是平台级单策略;需要拆分会话类型,还是先只做 DM?
  6. 是否接受把 Baileys 返回的 message key 作为 reply-receipt-checked 的证据?如果不接受,首个切片只声明 reply-text-checked + reply-fence-checked。

10. 完成定义(第一个切片)

  • fork 同步 PR 合并;BotHarness 开发 pin 单独 PR 通过 --im-provider 启动校验。
  • dsh-im 暴露 WhatsApp checked DM text consumer:账号 fingerprint、独占收件、source proof、checked reply、fence、relink 失效。
  • BotHarness 识别 dsh-im/whatsapp:绑定、DM Grant、Source Event、Inbox、Outbox、CLI、设置页、二维码授权。
  • 真实 QA 账号完成一次 self-chat 文字 → 模型 → 原会话回复;重复投递/错误账号/relink/未知结果有回归。
  • 双语连接指南 + changes/ 片段 + qualification ledger(明确“开发来源”);pnpm lint / test / typecheck / format:check 通过。
  • 截图/录屏脱敏,未出现 QR、手机号、JID、私聊正文;Human QA 记录与自动化分开。
  • 产品 Provider pin / npm 发布 / 生产 Profile 均未改动(后续独立决定)。

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:fullstackEnd-to-end Host and Client implementationfeature:messagingMessaging module and external providershelp wantedExtra attention is neededready-for-humanRequires human implementationscope:hubParent coordination map or epic; not a standalone implementation slice

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions