Repository navigation
Description
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,比上游fc2ceab2ahead 168 / behind 338。本地 clone 可能更旧,先 fetch 再判断。 - BotHarness 的开发 pin 是
scripts/dev-im-provider.mjs里的beaed4a6,不是 fork tip;产品 artifact pin 又是另一套文件。不要把三者混为一个“版本”。
- 它保留上游 channel,同时叠加 checked Provider/Consumer 契约;
BotHarness/DeepSeekBot当前只识别 5 个 IM 平台:packages/core/src/messaging/dsh-im.ts的createDshImProvider(..., platform)与 inbound schemapackages/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. 硬规则(请先读,避免白做)
- 一个 PR 只做一个可运行的切片。 不要把 fork 同步、Provider、主项目 UI、群/媒体混在一个 PR。
- 不要 force-push / rebase 已发布的 fork
main。 BotHarness 按 SHA + runtime digest pin;重写历史会让已有 Profile 无法复现。同步用 merge commit。 - 不要改产品 Provider pin,不要发布 npm,不要动生产 Profile。 开发 pin 和产品 pin 是两回事。
- 不要提交任何 WhatsApp 凭据、auth state、QR、手机号、JID、聊天正文或未脱敏截图。 使用专用 QA 手机/账号,不要用个人主号。
- 一个账号只能有一个 receiver。 复用
exclusive-inbound-consumers,不要起第二个 standalone dsh-im Session,也不要让两个 Host 同时收同一账号。 - 没有原生证据就不要声明能力。 Baileys 返回的 message key 不等于“服务端已送达/已读”;不确定时只暴露
reply-text-checked/reply-fence-checked,不要加reply-receipt-checked。 - 不要全局替换
weixin特判。 WhatsApp 和微信的会话语义不同(linked device、群触发、JID/LID、媒体编码)。逐个位置判断。 - 不要把 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 --pruneDoodleBears/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.mjsplugin-src/host/delivery-adapter.mjsplugin-src/host/delivery-service.mjsplugin-src/host/app-setup.mjssrc/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/*.jsWindows 上用 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 确认四件事:
- 连接方式:继续用现有 Baileys / WhatsApp Web linked device,还是改走官方 WhatsApp Business Cloud API?
- 如果选官方 Cloud API,Provider 层要重新设计(webhook、Meta App、phone number ID、模板消息),本 handoff 的 B1 不适用。
- 首个切片:self-chat / paired-owner DM 的文字收发,是否就是你要的 tracer?
- QA 账号:谁提供专用手机/WhatsApp 账号?谁授权扫码链接?不要用个人主号。
- 公开边界:这个切片是否只作为开发 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。精确使用 Baileyskey.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.mjsdescribeDeliveryAccount(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 重新校验,发送前调用beforeSendfence;用 Baileys 在原始 chat 发送(带 quoted message key)。返回值只声明真实拿到的结果。- 首个切片不要实现
postConversationChecked/listReachableConversations/beginTypingChecked/historyChecked,除非你已经能证明它们;没有它们时 proactive / typing / history 自然不可用。
src/channels/whatsapp/whatsapp-runtime.mjsexternal-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.mjscreateDeliveryAdapter已经是通用的,不需要新增 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.tsMessagingInboundEvent.channel加'whatsapp'MessagingSetup.platform加'whatsapp'
packages/core/src/messaging/dsh-im.tscreateDshImProvider的 platform unioninboundSchema的channelenum- 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.tsmessagingDefaultsPlatform加'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的升级/新库用例。
- 当前最新 migration generation 是 105;新增一个 >105 的 migration,按 generation 69(WeChat defaults)的做法重建
packages/core/src/bots/cli-messaging.tsPLATFORMS加'whatsapp'
packages/core/src/bots/cli-im-authorization.tsPlatformunion、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 指引。不要默认放行。
- 决定 WhatsApp owner DM 是否支持
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:platformunion 加whatsappcreate-app-form.tsx:QR 状态 / 文案 / 提交external-identity-list.tsx:平台行、DM-only 提示、教程链接messaging-defaults-settings.tsx:平台选项与说明bridge-source-label.ts:whatsapp标签bridge.ts:事件 channel guardmessaging-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
- 如果 UI 路径发生变化,更新
- 测试
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 客户端真的收到回复。
- Provider 合同:dsh-im
npm run check全过;新增消费/回复/fence/relink 回归。 - 隔离 Host:更新开发 pin 后,用
node scripts/dev-instance.mjs --home <tmp> --port <n> --im-provider启动;helper 必须先通过 runtime digest 校验。确认一个真实模型 DM 能回复(先排除模型/凭据问题)。 - 扫码链接:用专用 QA 手机/账号扫码;确认绑定行、账号 fingerprint、连接状态。
- 首个真实 tracer:
- 在 self-chat 发一条唯一标记文字;
- 确认恰好一条 canonical Source Event、一条 Inbox Admission;
- 真实模型产生一次
bridge_reply; - 在原 self-chat 看到同一个账号的回复;
- Outbox 有记录的 receipt / unknown 状态,未自动重试。
- 边界回归:重复投递、错误账号、relink/注销后旧 route 失效、发送前撤销 Binding/Grant、未知发送结果不重试。
- 证据:截图/录屏只保留脱敏后的设置页、绑定行、source details、原生回复;二维码、手机号、JID、聊天正文必须裁掉或打码。按
verify-deepseekbot技能留 ARIA/console/截图;Human QA 与自动化分开记录。 - 文档:先写“开发 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. 第一个星期可以这样走
- 读下面“阅读清单”的前四项;在这个 issue 下留言,说明你的时区、是否有专用 WhatsApp QA 账号、想先做哪一步。
- 等 maintainer 确认 B0 的四个问题;不要先写 UI。
- 做 Workstream A:同步 fork,
npm run check通过,开 PR。 - 做 B1:WhatsApp checked DM text + 单测;用 dsh-im 自己的测试证明契约。
- 做 B2/B3 的最小垂直切片:一个 DM 文字 → Inbox → 模型 → 原生回复;先跑通,再补 UI 文案/教程/文档。
- 把真实证据和未覆盖项写进 PR;等 Human QA 后再讨论群/媒体。
如果时间有限,只完成第 3 步也是有价值的交付:fork 同步本身就是当前最大的阻塞项。
7. 阅读清单
先读:
AGENTS.md— 命令、目录、交付流程、CLI parity、验证要求CONTRIBUTING.md— 首次贡献、PR、证据要求CONTEXT.md— PersonaBot / Channel / Source Event / Inbox / Outbox 等术语docs/dev/guides/im-provider-integration.md— 本任务最重要的边界文档docs/architecture/botharness-architecture.md— 当前架构
按需读:
- ADR-0101 — checked account/target
- ADR-0104 — 隔离 Profile 与 fork pin
- ADR-0127 — 独立 Provider 产物
- ADR-0128 — checked reply / 原生路由
- ADR-0139 — owner-context / 主动发送 fence
- ADR-0151 — reply-only / source proof
- ADR-0161 — CLI 授权 attempt
- ADR-0197 — 主动发送 / Outbox
docs/wechat-connection.md与docs/qq-connection.md— 最接近的两个产品切片- dsh-im 的
README.en.mdWhatsApp 段、src/channels/whatsapp/、src/channels/weixin/、src/channels/qq/ dsh-plugin-dev、dsh-dev、verify-deepseekbot、dsh-uiskills(仓库.agents/skills/)docs/agents/agent-work-trace.md、docs/agents/pr-merge-risk.md、docs/agents/pr-ui-visual-evidence.md、docs/agents/changelog.md
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 先回答的问题
- 我们接受 Baileys / WhatsApp Web linked device 作为开发 tracer 吗?如果只接受官方 WhatsApp Business Cloud API,请明确,B1 需要重写。
- 首个切片是否就是 self-chat / paired-owner DM 文字?还是希望先做群 @?
- 谁提供并授权专用 QA 手机/账号?扫码链接的同意窗口由谁执行?
- WhatsApp 在产品里是否只作为“开发来源 / 未发布 capability”,直到真实验收?产品 pin 和公开文档的升级条件是什么?
- 平台默认值怎么处理:DM 要
all/immediate,未来群要mentions/digest,现有messaging_default_revisions是平台级单策略;需要拆分会话类型,还是先只做 DM? - 是否接受把 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
Labels
Type
Projects
- StatusShow more project fieldsTodo
- StatusShow more project fieldsTodo
Activity