Files
dsh_ai1net_server/交付物/手机接入-目标与协同计划-20260929.md
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次)
- .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…),
  目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪
- .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/)
- .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*)
- .gitignore 补:备份件(*.bak-*)
- 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

111 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 手机接入 · 目标与协同计划(2026-09-29)
> 工作区 `E:/ProgramData/AIProject/ai1net-dsh-server`(**本工作区 = 目标与协同的唯一入口**)
> 权威架构 = `交付物/手机App经覆盖网络操作WorkBuddy-架构定稿v2-20260928.md`
> 工单 = `ai1net-dsh-anywhere/docs/交接单/对接单_WorkBuddy手机客户端-Android_20260928.md`
---
## 一、目标(终态,一句话)
**手机 App 通过 ai1net 覆盖网络(HTTPS 443)操作自己电脑上的 WorkBuddy 会话,能力做成 DSH 插件**
(`@dsh-local/ai1net` 的客户端半 + 平台半**同一个包**),并由**账号核对**保证「我的账号只能连我的客户端、访问我的 WorkBuddy」。
### 验收判据(终态,全部要过)
| # | 判据 | 怎么验 |
|---|---|---|
| V1 | 手机(真机、非 USB)能看到桌面会话列表与最新消息 | 设备入口地址 `https://<门户>/u/<uid>/desk/<hostId>/…` 打开即见 |
| V2 | 手机发出的消息**进入桌面会话**(任意同项目会话) | 目标会话 `replay` 出现 `user_message_chunk`,文本逐字一致 |
| V3 | 桌面正在用的会话不被夺走(发消息不产生 writer 冲突) | 活会话路径走 `reply`;非活会话走 ACP 借用并归还 |
| V4 | `src/net/relay/**` 零协议改动(不复用第二套中继) | 该目录无新增 op |
| V5 | 权限面不扩大:**不开任何对外端口**、准入四道闸保持、默认关 | 端口清单 + `device_web_enabled` 默认值 |
| V6 | 插件形态正确:垫片是 **DSH 客户端插件**(并入 ai1net 包第 6 模块),⛔ 不是独立进程 | 包内模块清单 + `dsh.profile.bundles` |
| **V7** | 🔴 **绝不影响 WorkBuddy 本身的运行(2026-09-29 用户明令)**:单向依赖,fail-safe 方向 = **关掉自己** | **见 v3 §0.5**(七条技术条款 T1–T7 + 六项验收):连续 1 h / ≥50 次操作期间 —— WorkBuddy pid 恒定 · 宿主会话能回 idle · 桌面"当前对话"未被改 · 无 429 · 无新增对外端口 · 配置目录哈希零差异 |
---
## 二、🔴 现状 vs 定稿:偏差表(**必须承认,不是按定稿实施的**)
近两天(`tmp/wb-phone/`)做的是**本机旁路原型 + 能力取证**,三处与定稿不符:
| 维度 | 定稿 v2 要求 | 我实际做的 | 判定 |
|---|---|---|---|
| **传输路径** | 手机经 **ai1net 设备入口**(443 + 覆盖网络)到电脑 | **USB `adb reverse` + 手机浏览器访问 `localhost:18899`** | ❌ **不符**(旁路) |
| **承载形态** | 垫片 = **DSH Host 插件**,只绑 `127.0.0.1:20090`,并入 `@dsh-local/ai1net` 第 6 模块 | 独立 Python 进程 `bridge.py`,绑 `127.0.0.1:18899` | ❌ **不符** |
| **凭据方式** | 首跳 `?password=` 换 Cookie,之后复用 Cookie(§5.3) | 实测 `?password=` 在受保护路径**永远失效** ⇒ 改 `x-access-token` 头 | ⚠️ **定稿需更正**(见 §三·C1) |
| **手机侧形态** | Android App(`com.dsh.client`,棒 3 产物) | 手机**浏览器**页面(APK 未安装) | ⚠️ 原型,未走 App |
**没打开 DSH 客户端的原因(如实说)**:**G-A 未解** —— `C:/Users/Administrator/.dsh/profiles/` 只剩 `rescue`/`web`,**没有 `desktop`**,垫片**无处可挂**。⇒ 棒 1 被这一条卡住。
**「手机 APP 插件功能在哪」**:架构里的「插件」指**电脑侧的 DSH 客户端插件(垫片)**,不是手机上的东西;手机侧只需要是 App。
而**插件目前还没做**(棒 1 未开工)。手机上你看到的是我起的**本机桥的浏览器页面**。
---
## 三、🔴 我方取证对定稿的 6 条更正(**回写 v2 → v3 前,各线按本清单为准**)
> 每条都有**源码实读 + 真机实测**双依据,脚本在 `tmp/wb-phone/`(⛔ 不入库)。
| # | 更正 | 依据 | 影响 |
|---|---|---|---|
| **C1** | 🔴 **令牌可自动取得,不再需要人工**:口令就在 `process.env.CODEBBUDDY_GATEWAY_PASSWORD`,**唯一稳定带法是 `x-access-token: <明文>`** | gateway 源码 `GatewayAuth.resolve`:env → settings → 随机生成;实测 env 值 + `x-access-token` ⇒ **200** | **§5.3「首跳换 Cookie」整段可删**;且 **v2 §1.1 的一条论据("凭据只在进程内存里 ⇒ 垫片必须进程内")被削弱** —— 需插件线复核是否还坚持"进程内" |
| **C2** | `?password=` 在 `requireAuth` 保护的路径上**永远失效** | 源码:`requireAuth` 构造请求对象时写死 `query:{}` | 照 §5.3 写必然踩坑 |
| **C3** | 🔴 **`Origin` 透传 ⇒ 写操作一律 403** | 实测:无 `Origin` → 409(正常);带 `Origin` → `403 {"error":"Origin not allowed"}` | §5.1「Origin 归一」**必须做,且是"剥掉"**,⛔ 不许走"给网关加 CORS 白名单"(那条违背红线) |
| **C4** | 🔴 **网关只读写"与自己同工作目录"的会话**;跨项目会话 `history`/`replay` 一律 **404 `SESSION_NOT_FOUND`** | 实测:同目录 5 条可达 / 跨项目 19 条不可达(直连网关亦然) | **对接单与架构都没写这条** ⇒ 手机端的会话列表必须按"可操作"过滤 |
| **C5** | 🔴 **「活会话」= 桌面当前打开的那一个**(`sessionManager.sessionSubject.value`),`reply` **只认它**;**往任意会话发消息要靠 ACP `session/load`+`session/prompt`** | 源码 + 实测(load 后 `/sessions/live` 切换;prompt 后目标 `replay` 出现 `user_message_chunk`) | 对接单「发送」一节需重写;另:**`session/load|new` 必须带 `cwd` + `mcpServers`**(缺则 `-32602`) |
| **C6** | ⚠️ **被 writer 占用的会话,外部接管不了**:`session/load` 报 `-32000 "already has an external writer" {reason:"writer_occupied"}` | 实测 | 「往任意会话发」的边界:**正被桌面占用的会话暂时发不进去**(空闲的可以) |
---
## 四、棒次、归属、依赖(按定稿 §6 + 本轮更正)
| 棒 | 归属线(工作区) | 做什么 | 判据 | 前置 |
|---|---|---|---|---|
| **棒 0** | ✅ 本工作区(已完成) | 端口发现脚本 + 取证 | 交付物 `棒0-…mjs` | — |
| **棒 0b** | ✅ 本工作区(已完成) | 手机经网关操作会话的取证与打通(含本节 §三 六条更正) | `交付物/棒0b-…md` | — |
| **棒 0c** | ✅ 本工作区(**已完成 09-29 07:2x**) | **把 §三 六条更正回写 → 出架构 v3**,并同步对接单/执行交接单 | v3 发布 + 两个工单同步 | 棒 0b ✅ |
| **🅐G-A** | 🔴 **desktop 线**(`ai1net-dsh-desktop`) | **恢复/确认 `desktop` profile 与垫片挂载点** | 给出 `desktop` profile 落点 + 加载证据 | — |
| **棒 1** | 🔴 **插件线**(`ai1net_ui`) | 垫片**归并入 `@dsh-local/ai1net` 第 6 模块** + 改造(上游改指 gateway、动态发现、去 `webServer`、凭据改 `x-access-token`、剥 `Origin`) | `curl 127.0.0.1:20090/api/v1/sessions` 返回 JSON;连续 50 次**无 429** | 🅐(挂载点)可并行做代码 |
| **棒 2** | 🔴 插件线(同包 · 平台半) | G-B:准入**零改动** ⇒ 装同一包 + 开关登记 | 经设备入口访问垫片通;两条通道互不影响 | 棒 1 |
| **棒 4** | 🟡 **手机接入线**(`ai1net-dsh-anywhere`)+ 三方联调 | 对接单同步更正 + 端侧按新契约调整 + 真机端到端 + 断网重连 | V1–V4 | 棒 1/2 + 棒 3(✅ 已完) |
---
## 五、协同分工(派活 · 一棒一线)
| 线(工作区) | 本轮派什么 | 为什么是它 |
|---|---|---|
| `ai1net-dsh-desktop` | **🅐G-A**:解 `desktop` profile 缺口 + 给垫片挂载点结论 | 桌面/客户端线的地盘 |
| `ai1net_ui` | **棒 1(+棒 2 代码半)**:垫片归并 + 改造 | 插件线的地盘(ai1net 包属它) |
| `ai1net-dsh-anywhere` | **对接单同步 + 端侧调整 + 联调准备** | 手机接入线的地盘 |
| 本工作区 | **棒 0c 回写 v3** + 全程协同/验收 | 本工作区是目标与协同的唯一入口 |
**纪律(各线必守)**:开工先抢锁(`bash D:/github/dsh_shenxian/dsh-server-docs/07-scripts/handoff-guard.sh --claim-exec "<会话名>" --domains <域>`)|做完 `--release-exec`|一次只做一件事、做完即停|⛔ 不替别线干活。
> 🔴🔴 **【收尾即叫监管 · 2026-09-29 新规 · 各线必须逐字执行】**
> **任何一棒做完后,必须立即创建一个一次性自动化把「监管棒」叫起来**,然后才停:
> - `name`:`协同监管棒 · 立即轮(<你的线> 收尾)`
> - `scheduleType`:`once`|`scheduledAt`:**当前时间 + 2 分钟**|`status`:`ACTIVE`
> - `cwds`:`E:/ProgramData/AIProject/ai1net-dsh-server`(监管棒跑在本工作区)
> - `prompt` 至少写:**「本工作区=手机接入协同监管。立即按 `交付物/手机接入-目标与协同计划-20260929.md` 与定稿 v3 做一轮:抢锁 → 收三线产出 → 判 V1–V7 → 覆写 `交付物/手机接入-进度看板.md` → 按缺口派下一棒(一棒一线,排期=收口+5~8 分钟)→ 追加当日记忆 → 释放锁并停。⛔ 不起常驻任务。抢不到锁只报告。」**
>
> **为什么必须这样做**:钩子**不能开新会话**(自动化才是唯一通道),而**整点轮询太慢**(你要的是"完成即推进")。
> ⇒ 由**完成方在收尾那一刻**叫监管棒,**延迟≈2 分钟**,且**不需要任何常驻进程**。
> ⛔ 不要等整点、⛔ 不要等用户催、⛔ 不要用会话后台任务去等(那会把宿主会话反复唤醒 ⇒ 用户看到"卡死")。
> 每小时那一轮 `1eaf45c3` 只是**兜底**(防链条断掉),不是主通道。
---
## 六、红线(不得触碰)
> 🔴 **【最高·2026-09-29 用户明令】做这些功能都不能影响 WorkBuddy 本身的运行,要禁止这种锁死,技术实现上要严格遵循。**
> 见 **v3 §0.5**(T1–T7 + 禁止清单 + V7 验收)。总则:**单向依赖,fail-safe 方向 = 关掉自己**。
> ⚠️ 已发生的反例(别再犯):把长跑服务放进**会话后台任务** ⇒ 每轮输出唤醒宿主会话 ⇒ **永不空闲 ⇒ 用户看到"卡死"**(我 09-29 违反 6 次复现)。
1. ⛔ **不给网关加 CORS 白名单 / 不开任何对外端口**(C3 的正解是"剥掉 Origin")
2. ⛔ **不动 `src/net/relay/**`**(V4)
3. ⛔ **不改 DSH 那条已验通的通道**(两条通道并存,端口/设备行分开)
4. ⛔ **令牌不落盘、不进平台库、不进日志**(现在靠 env 自动取,恰好最干净 —— 别退回"写文件")
5. ⛔ **动 `E:/github/dsh-client` 前先入库**(该仓 0 commit)