# weixin-db E2E 验证报告(架构 C, 2026-05-12)

> 执行方式:subagent-driven-development。
> 本文档记录 plan `docs/superpowers/plans/2026-05-12-weixin-db-channel.md` 的完成情况、自动化验证结果、剩余手工 E2E 清单。

## 完成状态总览

| 阶段 | Tasks | 状态 |
|---|---|---|
| Phase C-0 · session.db schema PoC | C0-1 | ✅ DONE |
| Phase C-1 · 清理作废代码 | Task 1-5 | ✅ DONE |
| Phase C-2 · runtime/weixin_db/ 纯函数模块 | Task 6-15 | ✅ DONE |
| Phase C-3 · weixin_db.ts 主服务装配 | Task 16 | ✅ DONE |
| Phase C-4 · agent_channel 集成 | Task 17, 18 | ✅ DONE |
| Phase C-5 · agent_channel_group 改用户主动添加 | Task 19, 20 | ✅ DONE |
| Phase C-6 · 前端 UX | Task 21, 22, 23 | ✅ DONE |
| Phase C-7 · 安装包 + Tray | Task 24, 25, 26 | ✅ DONE |
| Phase C-8 · 端到端手工验证 | Task 27 | ⏳ 待用户跑 |
| Phase C-9 · 回复路径 5.7 | 占位 | ❌ (独立 spec) |

## 自动化验证结果

### 1. session.db / contact.db schema RE (Phase C-0)

脚本: `packages/backend/poc/weixin-4x/poc-13-session-schema.mjs` + `poc-14-contact-schema.mjs`
结果文档: `packages/backend/poc/weixin-4x/README-session-schema.md`

关键发现:
- **Msg 表名算法确认**: `tableName = 'Msg_' + md5(username)` (100/100 命中)
- **session.db 主表**: `SessionTable.username`(列出所有会话)
- **群显示名来源**: contact.db 的 `contact` 表 (`remark > nick_name > username`)
- 依此真实 schema **回填**了 `room_resolver.ts`(Task 12),不再是假设。

### 2. key 抽取 PowerShell 脚本冒烟(Task 10)

```bash
powershell.exe -ExecutionPolicy Bypass -NoProfile -File packages/backend/tools/win32/extract-weixin-key.ps1
```

实际输出(2026-05-12 测试):
```json
{"seedDir":"C:\\Users\\lixin\\Documents\\xwechat_files\\shin_seed_7861",
 "wxid":"shin","wechatVersion":"4.1.8.107","pid":39916,
 "dbKeys":{"message_0.db":"374c4e1a...","session.db":"e43bd85c...","contact.db":"bd93ce66...",...}}
```

✅ 17 个 DB 的 key 全部成功抽取。

### 3. 后端单测 (与 weixin-db 相关的 suite)

```
pnpm --filter @neta/backend test -- netaclaw/runtime/weixin_db netaclaw/service/weixin_db netaclaw/service/agent_channel netaclaw/service/agent_channel_group

Test Suites: 13 passed, 13 total
Tests:       92 passed, 92 total
Time:        7.954 s
```

覆盖:
- `runtime/weixin_db/` 全部模块(wcdb_codec / zstd_decode / db_paths / key_extractor / message_repo / room_resolver / wal_watcher / build_pseudo) — 均 TDD 通过
- `service/weixin_db.ts` — 5 个 case (`replyToGroup` 占位 throw、`bindChannel` 在/非 Windows、`refreshWhitelist`、`unbindChannel` 幂等)
- `service/agent_channel.ts` — 含 17+9+6 测试:page enrichment 切换为 weixin-db、group 路由经 findByKey + replyToGroup、delete 走 unbindChannel、toggle 刷新 whitelist
- `service/agent_channel_group.ts` — 27 个测试:addByName 新语义、toggle 不再接受 -1、updatePolicy 拒绝 prefix 等

### 4. Tray .NET 单测(Task 26)

```
dotnet test packages/windows-tray/Neta.Tray.Tests
已通过! - 失败: 0,通过: 5,已跳过: 0,总计: 5
```

删除 `BridgeProcessManager` / `BridgeHealthPoller` / `BridgeProcessManagerTests.cs` 后,Neta.Tray 仅管理 backend.exe,5 个剩余测试全通。

### 5. Installer 脚本(Task 24, 25)

- `build-windows-installer.js`: 删 bridge dotnet publish 步骤,加 `tools/win32/*.ps1` 拷贝步骤
- `setup.iss`: 删 `bridge-output\*` / bridge.exe uninstall taskkill;加 `tools-output\win32\*` → `{app}\tools\win32`

语法检查通过,实际 `iscc` 构建需在 Inno Setup 环境下执行,未包含在本次自动化验证中。

## 手工 E2E Checklist (Task 27)

以下需用户在真实 Windows + PC 微信环境手工跑:

- [ ] **E2E-1**: 前端新建 channel type=`微信本地代理（群聊）`,填 wxid `shin` → 保存成功
- [ ] **E2E-2**: backend 启动时看日志 `[weixin-db] channel X bound, wxid=shin ver=4.1.8.107 pid=XXXXX`,无 error
- [ ] **E2E-3**: 前端"群聊管理"打开,显示"已添加监管 0 个群" → 点 "+ 添加群" → 输入测试群完整名 → 提交
- [ ] **E2E-4**: backend 日志 `addByName created=true`;`netaclaw_agent_channel_group` 多一行 status=1
- [ ] **E2E-5**: 测试群里发"hello"(触发策略 at_mention) → backend 看到 `[weixin-db] incremental read` 但 agent 不回(at_mention 未命中)
- [ ] **E2E-6**: 群里发 `@机器人 你好` → routeInboundMessage 走 handleInboundMessage group 路径 → agentExecutor 执行 → replyToGroup throw 占位 → 日志 `weixin-db reply 暂未实现, cid=X room=测试群 skipped`
- [ ] **E2E-7**: 切到"所有消息"策略 → **未加白名单的群**发消息 → backend 完全没反应(白名单过滤生效)
- [ ] **E2E-8**: 白名单群发消息 → backend 看到处理
- [ ] **E2E-9**: 前端删除该群白名单 → DB row 消失 → 再发消息 backend 无反应
- [ ] **E2E-10**: 关 Weixin → wal 不变,backend 平静;重开 Weixin → 健康探针触发 → 自动 rebind(60s 内)

## 关键技术决策记录

1. **架构 C**: 纯 Node + PowerShell(无独立 .NET bridge 进程)。ps1 脚本 spawn 一次抽 key,后续 Node 本进程处理。
2. **零被动发现**: 群必须用户主动添加,白名单在 DB 解密阶段即过滤,bot **物理上读不到**非白名单群消息(隐私保护)。
3. **回复路径占位**: `replyToGroup` 当前 throw NotImplementedError,`agent_channel.handleDbInbound` try/catch 跳过,不阻塞读链路。spec 5.7 独立 plan 实施。
4. **跨平台兜底**: 非 Windows `loginStatus='unsupported_platform'`,不 spawn powershell 不 crash。
5. **重连机制**: WeixinDbService 60s 健康探针,基于 `process.kill(pid, 0)` + `fs.accessSync` 判断 Weixin 进程 + DB 可读。

## 遗留 Follow-up

1. **Task 27 E2E**: 待用户跑,目前仅自动化部分已验证。
2. **Phase C-9**: replyToGroup 真实实现(5.7)需独立 spec(剪贴板/UIA/WCF 等方案待 brainstorm)。
3. **bigint 字面量**: `tsconfig.target=es2018` 不支持 `999n` 字面量,实现处用 `BigInt(...)` 构造(已注意)。
4. **zstd API**: `@mongodb-js/zstd` v2 只有 async,tryDecompressToString 已 async(plan Task 8.1 兜底方案)。
5. **better-sqlite3 + zstd native bindings**: root `package.json` `pnpm.onlyBuiltDependencies` 已包含两者,`prebuild-install` 会在 pnpm install 时正确执行。

## 文件清单

### 新增

**后端 runtime**:
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/wcdb_codec.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/zstd_decode.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/db_paths.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/key_extractor.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/message_repo.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/room_resolver.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/wal_watcher.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/incremental_reader.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/types.ts`
- `packages/backend/src/modules/netaclaw/runtime/weixin_db/build_pseudo.ts`
- `packages/backend/src/modules/netaclaw/service/weixin_db.ts`

**后端测试**: 上述所有模块对应的 `.test.ts`,以及 `test/modules/netaclaw/service/agent_channel.weixin_db.test.ts`

**工具脚本**: `packages/backend/tools/win32/extract-weixin-key.ps1`

**PoC**:
- `packages/backend/poc/weixin-4x/poc-13-session-schema.mjs`
- `packages/backend/poc/weixin-4x/poc-14-contact-schema.mjs`
- `packages/backend/poc/weixin-4x/README-session-schema.md`
- `packages/backend/poc/weixin-4x/session-schema-output.log`
- `packages/backend/poc/weixin-4x/contact-schema-output.log` (若写了)

### 修改

**后端**:
- `packages/backend/src/modules/netaclaw/service/agent_channel.ts`(weixin-uia → weixin-db 全替换,-147 行净删)
- `packages/backend/src/modules/netaclaw/service/agent_channel_group.ts`(upsertOnInbound → addByName)
- `packages/backend/src/modules/netaclaw/controller/admin/agent_channel_group.ts`(加 /add)
- `packages/backend/src/comm/path.ts`(删 pWechatUploadsPath)
- `packages/backend/src/config/config.default.ts`(删 wechatUploads 静态映射)
- `packages/backend/scripts/build-windows-installer.js`(删 bridge publish,加 tools/win32 拷贝)
- `packages/backend/installer/setup.iss`(删 bridge 项,加 tools 项)
- `packages/backend/package.json`(加 @mongodb-js/zstd)

**前端**:
- `packages/frontend/src/modules/agent/types/index.d.ts`(类型切换)
- `packages/frontend/src/modules/agent/views/channel-management.vue`(文案+字段)
- `packages/frontend/src/modules/agent/components/channel-group-panel.vue`(大改 UX,用户主动添加)
- `packages/frontend/src/modules/agent/composables/useDbChannelValidation.ts`(改名 from useUiaChannelValidation.ts)

**根**:
- `package.json`(加 pnpm.onlyBuiltDependencies)

**Tray**:
- `packages/windows-tray/Neta.Tray/TrayApplicationContext.cs`(删 bridge 拉起逻辑,316→169 行)

### 删除

- `packages/backend/src/modules/netaclaw/service/weixin_uia.ts` + `wechat_archive.ts`
- `packages/backend/src/modules/netaclaw/controller/open/weixin_uia.ts` + `admin/wechat_archive.ts`
- `packages/backend/src/modules/netaclaw/runtime/wechat_uia_routing.ts` + `wechat_archive_schema.ts`
- 对应 test 文件 6 个
- `packages/windows-tray/Neta.WeChatBridge/` + `Neta.WeChatBridge.Tests/` 整个目录
- `packages/windows-tray/Neta.Tray/BridgeProcessManager.cs` + `BridgeHealthPoller.cs`
- `packages/windows-tray/Neta.Tray.Tests/BridgeProcessManagerTests.cs`
- `packages/frontend/src/modules/agent/components/wechat-archive-panel.vue`
- `packages/frontend/src/modules/agent/composables/useUiaChannelValidation.ts`(被 useDbChannelValidation.ts 替代)
