仓库清理:memory 移出仓库 + 行尾规范化 + 执行会话目录排除 + docs/pm 入库

用户拍板三条(2026-10-15):「1、memory 不入仓库」「2、A方案」「3、A方案」

1、`memory 不入仓库`(推翻旧口径):`.gitignore` 增 `.workbuddy/memory/`,
   并把原注释「⛔ 保留 .workbuddy/memory/ 等知识文件」标注作废;已入库的 293 个文件
   用 `git rm -r --cached` 移出索引(⛔ 不动磁盘 —— memory 留在本机照常用,
   只是不再跟仓库走)。连带删掉被新规则覆盖的冗余行 `.workbuddy/memory/.backup-*/`。

2、行尾规范化(A 方案):新增 `.gitattributes`(`* text=auto eol=lf`)。
   起因:仓里原先没有属性文件、`core.autocrlf=false`,编辑器写成 CRLF 时 git 认为
   "整文件都改了"(实测 49 个文件 24816 增 = 24816 删、内容零变化),污染 diff 且每轮刷屏。

3、执行会话目录排除(A 方案):`.gitignore` 增 `执行会话/`(内含 160 个文件,
   多为 `_gate-out-第N切片.txt` 这类过程性中间输出);同时把该入库的 `docs/pm/`
   (ai1net-plugin 产品调研 9 份:1a 需求 / 1b 竞品+4 份独立分析 / 1c 画像 / 1d 策略 / 1e 场景)入库。

验收:提交前 `git status` 未暂存剩余 0(清理前为 78 项)。
This commit is contained in:
admin committed 2026-10-15 20:59:57 +08:00
1 parent 470a0bb5ce
commit 32a0fdd23c
304 files changed
+1127 -53847

No files matched your search

@@ -0,0 +1,99 @@
# 1a · 需求文档 —— AI1NET 基础插件(`@dsh-local/ai1net`)
> 规划对象:`@dsh-local/ai1net`(AI1NET 基础插件),代码在 `E:/ProgramData/AIProject/dsh-plugin-ai1net`(本轮只读)。
> 项目 slug:`ai1net-plugin`。落点:`docs/pm/ai1net-plugin/research/`。
> 方法:`grill-me` 两节(A 节=做什么 / 为谁 / 边界;B 节=做成什么样 / 哪些情况不成立 / 状态怎么流转)。
> 本轮用户不在场,按技能规则自行给推荐答案并逐条标 `【假设】`。
**状态行:已确认 9 项(全部来自上游件的用户拍板)/ 模型补全 14 项(未经本轮用户确认)。**
9 项确认的出处:`05-交接单/交接单_包规格书_20260926.md §四 D1–D6`(用户 2026-09-26 13:30 拍板「先备份现有代码,然后都按照 A 方案执行」)+ `交付物/全功能承载判定-底层插件能否承-20260926.md §3.12`(用户 2026-09-26 13:0x 原话)。14 项补全逐条见文末《待复核清单》。
---
## 是什么、为谁、不做什么
**一句话**:用户装官方 DSH 再加这一个包,就拿到 AI1NET 平台的全套业务能力。
**做什么**:把散在两处的六块业务能力(模型管理、技能插件管理、IM 插件侧、设备接入、多租户界面、覆盖网络界面)收进**一个插件包**。一份代码两处加载:业务逻辑与界面跑在用户实例(或桌面壳)内,要写平台库的那半跑在平台进程里。
**为谁**:
- 第一是**平台租户**。他在自己的实例或桌面壳里,用设置面板里那几张卡片管自己的模型、插件、IM、设备接入。
- 第二是**第三方插件作者**。他引包内 SDK(IM / 插件 / 模型三套),就能把自己的能力接进这套机制,不必自己重造轮子。
- 第三是**平台与运维侧**。一个发行单元意味着一次安装、跨端一致、更新只更一个包。
**不做什么**:不起实例(那是部署方案的事,K8S 或 systemd 随部署选);不取身份、不把自己装进去(这两件归引导层,信任根不能自举);不动官方 DSH 主程序与缓存;不重造分发与更新机制;本轮不改一行代码。
---
## 现状:六块模块,已落地四块
| 模块 | 内容 | 状态 | 落地形态 |
|---|---|---|---|
| M5 | IM 插件侧 | ✅ 已实现 | 三条精确路由 + 每插件令牌 + 实例级单例长轮询闸 |
| M3 | 技能插件管理 | ✅ 已实现 | 七条精确路由;「更新」四拆里第三、四拆的执行者在包外 |
| M2 | 模型管理 | ✅ 已实现 | 三条精确路由 / 六种方法;明文密钥只走 `credentials` POST 一个入口 |
| M6 | 设备接入 | ✅ 已实现 | 零宿主路由;在 `127.0.0.1` 占一个口做本机反代,上游口动态发现 |
| M1 | 多租户 | ⛔ 未接入 | 只有数据面表;「创建隔离实例」这个动作天然归平台进程 |
| M4 | 覆盖网络界面 | ⛔ 未接入 | 只有数据面表;入网凭据归引导层,不进包 |
包的其他既有事实:库名 `dshs_pl_ai1net`(已建,8 表 / 29 列);表前缀 `p_ai1net_`;两端都用同一份代码(host 半走 `connection.fetch.register` 精确路径,client 半走 lazy-CJS 封包)。
---
## 决策表
### A 节 · 要做什么、为谁、边界在哪
| # | 问题 | 决策 | 来源 | 理由 | 影响范围 |
|---|---|---|---|---|---|
| A1 | 要解决什么问题 | 能力散在平台 `src/*` 与实例侧两处,用户要有全套能力就得装多份东西;且桌面端只认精确路径、没有 `webServer`,把平台界面直接搬过来在桌面端根本不成立 | 【事实】(上游件 §3.12.6 + 方案 §1.3 实测) | 一个包做发行单元,是唯一能同时满足「一次安装」与「两端跑」的形态 | 1b / 1d / 1e 全篇;②段功能清单 |
| A2 | 成功怎么衡量 | 三条:装官方 DSH + 一个包即拿到全套能力;服务器壳与桌面壳装同一个包;更新只更一个包 | 用户拍板(§3.12.4 收益三条) | 这三条正是「收敛成一个包」的全部收益,别的指标都是附带的 | 1d 北极星与 OMTM |
| A3 | 谁最痛 | 租户。他要在一个地方把自己实例的全部能力管起来,现在这些能力分散、且有的压根没有界面 | 【假设】(依据:M1 / M4 两块只有表、没有界面 ⇒ 需求存在但未被满足) | 痛点排序决定第一版做什么 | 1c 画像;②段优先级 |
| A4 | 用户是谁 | 两类人直接用手:租户(自管模型 / 插件 / IM / 设备),第三方插件作者(用 SDK 接入)。平台与运维是间接受益者 | 【假设】(依据:包内三套 SDK 的 `exports` 已挂出,说明 SDK 是给外人用的) | 用户决定界面薄到哪一层、SDK 稳到什么程度 | 1c 三个画像;1d 市场切分 |
| A5 | 用户现在怎么凑合 | 平台侧堆界面:把管理面写在平台进程的 `src/web/routes/*` 里。桌面端因为没有 `webServer`,这条路走不通,桌面用户只能不用或退回命令行 | 【事实】(方案 §1.3 实测交集表) | 替代方案有真实成本(桌面端不可得)⇒ 这个问题值得做 | 1e 场景;1d 价值主张 |
| A6 | 第一版做什么 | 已经落地的四块(M5 / M3 / M2 / M6)就是第一版的实体:能装、能跑、能取数、能回调 | 用户拍板(§四 D6:首个迁移块 = IM 插件侧) | 先按最短的路把形态跑通,再补内容 | ②段功能清单;③段界面 |
| A7 | 明确不做什么 | ① M1 多租户的管理动作(要写平台库,插件没这个权限)② M4 覆盖网络的取身份 ③ 起实例 ④ 取身份 ⑤ 把自己装进去 ⑥ 改官方 dsh ⑦ 重造分发与更新机制 | 用户拍板(§3.12.3 / §3.12.5 / §四硬边界) | 少一样都不成立:这几件要么要更高权限,要么要发生在插件存在之前 | ②段「不做哪些」;1d 取舍 |
| A8 | 交付形态:价值在哪一层 | 契约与包结构为主,界面为辅。值钱的是「只用两端都存在的扩展点」这条约定、三套 SDK、数据面声明。五张卡片只是这套约定的可见面 | 【假设】(依据:host 半的复杂度远高于 client 半,且门禁 ①c–①h 逐字断言契约) | 价值在哪一层决定界面复杂度的上限:答「约定为主」,界面就必须薄 | ②段界面布局;③段 D0 |
| A9 | 交付形态:有几个界面 | 两个层面。**实例/桌面壳**:设置面板「插件」区下五张卡,每张卡只办一件事(骨架探针 / IM / 技能插件管理 / 模型管理 / 设备接入)。**平台进程**:零界面,只接受请求 | 【假设】(依据:client.js 五张卡各自独立槽位条目;平台不是实例、装不了插件) | 结构性决策,漏了它后面所有界面文档都要重做 | ②段 2b;③段全部页面 |
| A10 | 交付形态:信息承载到哪一层 | 一进来就看到:卡名 + 一句话状态(`view:'summary'` 分支)。点进去才看到:条目列表、密钥输入、授权开关 | 【假设】(依据:官方 `plugins.item` 槽位先用 summary 取一句话、再用正文渲染同一张卡) | 决定「信息墙」会不会发生 | ②段分档表;③段布局 |
| A11 | 手上已有什么 | 包已在机(S2–S8 五个棒次);库已建(8 表 / 29 列);两端接入方式已跑通;平台侧共享包库与三只只读口已在机 | 【事实】(包内 README + §3.12.4 + 方案 §0 边界 1) | 有存量就不用重建,直接在这套约定上长 | 1d 能力;②段开工前置 |
| A12 | 还缺什么才能验证 | ① 平台侧插件宿主(平台进程现在还跑不了这个包)② 桌面侧拉取器 ③ 覆盖网络定稿 F1.5 ④ 插件数据面部署到 47 / 106 | 【事实】(§4 缺什么汇总表) | 缺口决定「什么能现在验、什么只能等」 | 1d 风险;③段验收 |
| A13 | 约束 | 只用两端都存在的扩展点交集(`connection.fetch.register` 精确路径 / `dsh.client` / index 注入);一个包一个 pluginId 一个库;改动只走官方插件与注入点 | 用户拍板(§四 D1 / D2 / 方案 §0 边界 2) | 越出这条交集,桌面端当场不可用 | 全篇;③段与开发段 |
| A14 | 依赖哪些外部系统 | ① DSH 插件机制(cordis:`inject` / `apply` / `effect`)② 平台进程的 HTTP 服务面 ③ 平台侧插件宿主(⚠️ 未建)④ 共享只读包库与版本维度 | 【事实】(包内 host 半全篇 + §3.12.3) | 依赖未建的那一项(③)是「平台那一半」落地的唯一前置 | 1d 风险;②段依赖条 |
| A15 | 竞品与替代 | 用户今天能拿什么替代:官方 DSH 插件族、本平台已有的 `dsh-plugin-mcn-suite`、平台侧内建管理界面、以及「一模块一包」的拆分形态 | 【假设】(依据:README 点名官方 `packages/subagent-local` 为参照实现;方案 §0 边界 1 提到 mcn-suite) | 替代方案决定我们要学的与要避开的 | 1b 竞品池;1d 差异化 |
### B 节 · 做成什么样、哪些情况不成立、状态怎么流转
| # | 问题 | 决策 | 来源 | 理由 | 影响范围 |
|---|---|---|---|---|---|
| B1 | 形态与骨架(粗粒度) | 实例/桌面壳侧:设置面板下五张卡。每张卡一个板块(状态行 + 条目区 + 操作区)。卡与卡之间不互相跳转,各挂各的槽位条目。平台侧:无界面 | 【假设】(依据:client.js 五张卡各自独立 `ENTRY_NS`;⛔ 精确板块清单归②段) | 粗粒度只确认「有哪几页、大概几个板块」,细的归②段 | ②段 2b《界面布局》 |
| B2 | 什么情况下这套东西不成立 | 三种:① 想用 `webServer` / 前缀路由 / 页面级路由 ⇒ 桌面端当场不可用 ② 想让插件替用户做「创建隔离实例」这类写平台库的动作 ⇒ 平台进程装不了插件 ③ 拿不到自己那枚装配凭据 ⇒ 一律拒(fail-closed),不做降级 | 用户拍板(§四 D2 / §3.12.3)+【事实】(README「残留①」) | 三条都是「做法本身失效」,不是异常 | ②段边界;③段 D0 判据 |
| B3 | 有哪些状态、怎么迁移 | 装载:`inject connection` → `apply(ctx)` → 逐条注册精确路由(每条用 `ctx.effect` 登记 dispose)。卸载:走 dispose,回原状。请求:取调用方身份 → 取「出示的凭据」→ 交内核 → 折成 HTTP 状态码 | 【事实】(index.js 全篇) | 无隐藏状态:装 / 卸 / 请求三段就是全部 | ②段状态流转;开发段 |
| B4 | 失败怎么办、谁兜底 | 拿不到 `connection` ⇒ 告警并少掉路由面,但⛔ 不抛;单条路由注册失败 ⇒ 不牵连其余;某个模块装配失败 ⇒ 少一个模块,但⛔ 不让整棵插件树挂不上;平台调用失败 ⇒ 具名 `reason` 映射到具名 HTTP 码(403 / 401 / 409 / 503 / 400),⛔ 不一律 502 | 【事实】(index.js 的 `warn` / `guard` / `statusOfReason`) | 少一个模块 ≠ 整包挂,这就是「可卸」的代价与收益 | ②段异常处理;③段空态 |
| B5 | 数据契约 | 输入:调用方身份 + 凭据 + 业务参数(JSON)。产出:JSON 响应 + 具名 HTTP 码。落库:**一个包 = 一个 pluginId = 一个库** `dshs_pl_ai1net`,表名必须带模块段(`p_ai1net_<模块>_<表>`)。声明载体 = `dsh.data.yaml`,由 `package.json` 的 `dsh.data.schema` 显式指向。包内零数据库动作 | 用户拍板(§四 D1 / D3)+【事实】(dsh.data.yaml + DB-03 §二 红线) | 表名分段是为了「一次迁移牵动不了六块」,每块能单独回滚 | ②段数据契约;开发段 |
| B6 | 谁能看、谁能改、越权怎么办 | 调用方身份取请求头 `x-dsh-im-plugin-id`,凭据取 `x-dsh-im-plugin-token`,令牌把(实例,插件)签死。带身份头却没带凭据 ⇒ 必拒,⛔ 不回退到本机 env。模型管理里:明文密钥只走 `POST .../credentials` 一个入口,读的路径根本没有密钥;共享模型要管理员逐用户授权,默认不共享 | 【事实】(README「残留①」+ index.js 的 `presentedOf`) | 「取不到自己那枚就拒」是治「插件自称身份」的唯一办法 | ②段权限;③段越权态 |
| B7 | 同一件事被做两次会怎样 | 路由:同一条路径只注册一次(官方重复注册会直接抛)。长轮询:实例级单例闸,第二条申请具名拒绝(`longpoll-already-running`),且真的不启动第二条。凭据写入:读路径无密钥,写路径幂等由平台侧保证 | 【事实】(README「残留②」+ index.js 注册段) | 单例闸治的是「每插件一条、吃光连接额度」 | ②段并发条;开发段 |
---
## 待复核清单(14 条 `【假设】`,未经本轮用户确认)
每条给出:为什么不成立会有后果 + 建议的回收时机。
1. **A3 痛点排序**(租户最痛):若实际最痛的是第三方插件作者,第一版的重心会押错。
2. **A4 用户是两类**:若 SDK 实际只给自己用,那「SDK 要稳定」这条约束可以放宽。
3. **A8 价值在契约层**:若判定为「界面层为主」,五张卡就要重新设计。
4. **A9 界面是两个层面、五张卡**:卡的数量与粒度若与用户预期不符,③段整轮返工。
5. **A10 信息承载分档**:分档错了会做成信息墙。
6. **A15 竞品池的四个对象**:漏了用户心里的那个,1b 的结论就用不上。
7. **B1 卡内三板块(状态行 / 条目区 / 操作区)**:粗粒度假设,②段需重新核。
8. **B2 的第三条(fail-closed 不做降级)**:若业务上需要「降级可用」,整条判据要改。
9. **M1 多租户不在第一版**:用户可能要求这轮就把界面做出来(只做界面、动作留平台)。
10. **M4 覆盖网络不在第一版**:同上。
11. **第一版 = 已落地的四块**:若用户要的是「六块齐了才算第一版」,范围与工期都要重估。
12. **M6 的启用默认值 = 不启**:安全默认,但用户可能希望默认启。
13. **平台侧无界面**:若用户希望在平台里也能看到一张总览页,A9 要扩一层。
14. **成功衡量的三条**:若用户另有验收口径(例如「不再需要装多个包」之外还有「内存占用」),要补。
**状态行核对**:已确认 9 项 / 模型补全 14 项(14 项未经用户确认)。本清单未经用户逐条回应,下游 1c / 1d / 1e 引用这 14 条时必须保留 `【假设】` 标记,不得升格为事实。
@@ -0,0 +1,88 @@
# 竞品独立分析 · `dsh-plugin-mcn-suite`(平台业务插件套件)
## 1. 它是谁、属哪一层、为什么纳入
- **是谁**:本平台(AI1NET)已有的一个业务插件套件,承载 MCN 内容工作台的业务能力(账号、视频、分析、创作记录等十一个域)。
- **属哪一层**:**直接竞品**(第一层)。它是**同一台机器、同一套投放机制、同一份数据面规范**下已经跑通的业务插件。
- **为什么纳入**:用户在平台上是先见到它的。他会问「ai1net 这个包和 mcn-suite 有什么区别、为什么不合成一个」。这个问题答不清,本产品的定位就说不明白。
## 2. 用途
- 形态:一个 DSH 业务插件包,host 半挂精确路由 + client 半出界面,业务数据走插件数据面(独立库)。
- 给谁用:平台上的内容运营者(MCN 工作台的使用者)。
- 干什么用:把「管账号、拉视频、做分析、记创作」这一摊业务装进实例,用户在自己的实例里操作。
- 证据等级:**L3–L4** —— 有真机读数(版本号、包大小、表清单、库名、台账行、备份件),出处 `交付物/MCN数据面接入-阶段一/阶段二-20260925.md`。⛔ 未读到它的源码本体,能力清单以真机探针读数为准。
## 3. 场景
- 进入方式:从实例界面进入(真机路由形如 `/mcn/api/account/persona`、`/mcn/api/account/videos`)。
- 操作路径:取不到:无界面实录,无法逐步记录。
- 核心步骤:部分可答 —— 从路由名可读出「看账号画像 → 看账号下的视频 → 看视频分析」这条链,但这是从接口名反推的,不是观察到的动作链。
- 系统帮了什么:**有据** —— 插件数据面替它管了 11 张表,用户不必自己碰数据库。
- 最终产出:取不到。
- 哪一步最省力 / 最麻烦:取不到。
**缺口**:无界面实录,操作链只能从接口名反推。要补,需要一次带录屏的实例内走查。
## 4. 能力
- **业务路由面**:在实例内挂自己的 `/mcn/api/*` 路由。解决「业务逻辑没地方跑」的问题。对用户的意义是功能真的能点。
- **插件数据面(独立库 `dshs_pl_dsh_plugin_mcn_suite`,11 张表)**:解决「业务数据存哪」的问题。对用户的意义是数据跟着插件走,不污染平台库。
- **`dsh.data.yaml` 声明 + 平台侧建库 + 台账**:解决「表从哪来」的问题。真机台账 `state=ready`、`schema_version=1`、`last_error=null`。对用户的意义是数据面状态可见,坏了有据可查。
- **版本投放与回滚**:走平台共享只读包库投放,保留 `0.3.9 / 0.3.14 / 0.3.15 / 0.4.0` 四份回滚素材。解决「升级坏了怎么办」的问题。对用户的意义是能退回上一版。
## 5. 机制
- **一插件一库**:库名从包名推(`dsh-plugin-mcn-suite` ⇒ `dshs_pl_dsh_plugin_mcn_suite`)。为什么这样设计——插件没有平台库权限,只能有自己的库 ⇒ 给用户的结果是**插件之间互不干扰**,某一家的表坏了不牵连别人。
- **共享只读包库 + 版本维度**:包不是塞进实例,而是发到共享层、实例按版本拉。为什么这样设计——多个实例共用一份包,省分发成本 ⇒ 给用户的结果是**一次投放多实例受益**,但代价是「共享层已更新、实例仍载旧版」这种不一致会发生(真机实测出现过:共享层 0.4.0、实例还载 0.3.15,要重启才生效)。
- **数据面走声明 + 平台侧执行**:插件只写 `dsh.data.yaml`,建库与迁移由平台侧执行器做。为什么这样设计——插件不能自己建库(没权限、也不该有) ⇒ 给用户的结果是**顺序被钉死**(先建库再投放),少了这个顺序就静默无数据面。
- **业务全在插件层、⛔ 不动内核表**:为什么这样设计——内核表是平台资产,改了同步影响所有租户 ⇒ 给用户的结果是他的实例定制不会牵动别人的实例。
## 6. 强在哪、弱在哪
强者(多组,每组四行):
- 能力表现:真机已跑通、有完整版本与回滚链(四份回滚包在位)。
- 在什么场景:一次要给多个实例上线同一块业务能力时。
- 相对谁:相对「每次手工改实例文件」的做法。
- 对用户什么结果:上线与回退都有据可查,出问题能退。
- 能力表现:数据面规范已落地并被真机验证(11 张表、台账 ready)。
- 在什么场景:插件要存业务数据时。
- 相对谁:相对「插件自己连库、自己拼 SQL」的做法。
- 对用户什么结果:数据隔离清楚,插件坏了不会拖垮平台库。
弱者(多组,每组四行):
- 能力表现:只管自己那一摊业务,不做跨业务的统一入口。
- 在什么场景:用户在实例里要同时管模型、IM、插件、设备接入时。
- 相对谁:相对本产品(一个包做统一入口)。
- 对用户什么结果:他要一个个插件找过去,各插件界面风格与入口位置互不相干。
- 能力表现:依赖平台共享层刷新 + 实例重启才生效,存在版本不一致窗口。
- 在什么场景:刚投放完新版本、实例还没重启时。
- 相对谁:相对「一次安装即生效」的理想形态。
- 对用户什么结果:他可能以为升级成功了,实际跑的还是旧代码(真机实测出现过)。
- 能力表现:包体偏大(0.4.0 为 324 件 / 1,962,024 B),且源码目录在版本库里是未跟踪状态。
- 在什么场景:要回滚或要复现某版本时。
- 相对谁:相对「源码受版本管理、出包可复现」的做法。
- 对用户什么结果:只能靠 sha256 与单据对账,找不到「当时改了什么」。
## 7. 对我们
**该借鉴**
- 机会点:一插件一库 + `dsh.data.yaml` 声明这条数据面范式。对应场景:插件要存数据。用户问题:数据往哪放、怎么隔离。它现在怎么做:声明文件 + 平台侧执行器建库,台账可见。建议方向:**整条照搬**(我们的 `dsh.data.yaml` 已经是同一套),并把「先建库再投放」的顺序写成硬约束。
- 机会点:共享只读包库 + 版本维度 + 回滚素材留档。对应场景:上线与回退。用户问题:升级坏了退不回去。它现在怎么做:每次 share 自动落盘 tgz。建议方向:照搬,并在收口清单里固定「回滚素材在位」这一条。
- 机会点:库内表名分段。对应场景:一个库装多块业务。用户问题:一次迁移牵动全部。它现在怎么做:靠表名区分域。建议方向:我们的六模块表名分段与之一致,继续沿用。
**该避开**
- 机会点:共享层刷新与实例生效之间的版本窗口。对应场景:刚投放完。用户问题:以为升级了其实没升。它现在怎么做:共享层立即更新,实例要重启才加载。建议方向:产品上必须把「当前实际载的是哪一版」做成可见读数,⛔ 不靠人记。
- 机会点:包源码不受版本管理。对应场景:需要回滚或复现。用户问题:说不清某版改了什么。建议方向:我们的包源码在 `dsh-plugin-ai1net` 工作区里,保持可追溯;每次出包留 sha256。
- 机会点:包体偏大(324 件)。对应场景:分发与更新。用户问题:下载慢、更新面大。建议方向:我们保持「一个包六模块」时,注意把 `dist/` 与源码分离,`files` 白名单收紧(我们已经在 `package.json` 里列了 `files`)。
**可突破**
- 机会点:把多块能力收进一个包,同时保住单块可回滚。对应场景:用户要一次拿到全套能力。用户问题:装多份、管多份。它现在怎么做:一个业务一套包。建议方向:用「一个发行单元 + 包内分模块 + 表名分段 + 单入口按模块迁移」拿到两边的好处,这是本产品相对它最明确的一处差异。
@@ -0,0 +1,96 @@
# 竞品独立分析 · `@dsh-local/dsh-plugin-partment`(空间与项目)
## 1. 它是谁、属哪一层、为什么纳入
- **是谁**:本平台的一个业务插件(A 案原型 v3)。让用户自己建空间、在空间里建项目(=群聊房间)、他人申请加入后一起聊,管理员审核与启停。业务全在插件层,IM 内核一字不动。
- **属哪一层**:**直接竞品**(第一层)。它跟 `@dsh-local/ai1net` 是**同一批人、同一套机制、同一个投放链路**下的两个包。
- **为什么纳入**:它代表「不做一个大包、一块能力一个包」的那条路的**已完成态**。拿它比,才能看出「聚合成一个包」换来了什么、付出了什么。它的全源码在本机(`E:/ProgramData/AIProject/dsh-plugin-group`),是本池里证据最硬的一份。
## 2. 用途
- 形态:一个 DSH 业务插件包 —— host 半(业务 + 数据面)+ client 半(侧边栏与详情页);数据面走独立库。
- 给谁用:平台上的普通用户(自己建空间、拉人一起做事)与管理员(审核与启停)。
- 干什么用:把「建空间、建项目、申请加入、一起聊、管理员管」这一摊装进实例,替代原先没有归属协作空间的做法。
- 证据等级:**L3** —— 全源码在机(`lib/` 五件、`demo/`、`test/`)+ README + `dsh.data.yaml` 注释即实测记录。未在真机上跑过,故不列 L4。
## 3. 场景
- 进入方式:从插件侧边栏进入(`lib/client.js` 的侧边栏 + 详情页),演示页三种身份可切(普通成员 / 项目创建者 / 管理员)。
- 操作路径:建空间 → 在空间里建项目 → 项目的加入策略决定别人怎么进来(`public` 自助加入 / `knock` 投申请单 / `invite` 只能被拉)→ 进来后群聊收发 → 管理员审核与启停。
- 核心步骤:① 建空间(写 `space_meta`,归属房间=空间自己)② 建项目(写 `project_meta`,归属房间=所属空间)③ 投申请单(写 `join_request`,归属房间=所属空间,这样申请人与创建者都在同一可见范围内)④ 创建者同意(追加 `state_event`:`knocking` → `accepted`)⑤ 内核拉人进群。
- 系统帮了什么:数据面替它管五张表;内核替它管建房、拉人、收发消息;`state_event` 表绕开了平台 `update` 恒失败的缺陷 —— 状态用「追加事件 + 倒序取第一条」表达。
- 最终产出:一个可用的空间 / 项目结构,成员在其中群聊,管理员能启停。
- 哪一步最省力 / 最麻烦:最省力的是**加入策略四档映射内核两档**(`public`/`knock`/`invite`/`private` → 内核 `open`/`invite`),用户不必理解内核;最麻烦的是**管理员跨主体审核**和**停用的服务端强制**,两者插件内做不到(见 §6)。
## 4. 能力
- **建空间 / 建项目**:内核建房 + 数据面写元数据。解决「用户没有自己的协作空间」的问题。对用户的意义是他能自助建、不必找运维。
- **项目目录可发现(含未加入的)**:数据面归属口径刻意设成「业务行挂在空间房间下」。解决「我怎么知道有哪些项目」的问题。对用户的意义是能先看见再决定加不加入。
- **申请加入闭环**:申请单 + 内核拉人。解决「公开加入失控、邀请又不方便」的问题。对用户的意义是成员进入有人把关,但不至于要一个个手动拉。
- **群聊收发**:走内核消息接口,插件只做 UI。解决「协作要能说话」的问题。对用户的意义是聊的能力由内核托底,插件不必自己实现消息。
- **管理员审核 / 启用 / 停用**:状态落插件库。解决「管理员要能管」的问题。对用户的意义是有人能兜底。⚠️ 只做到一半(见 §6)。
- **状态机(两块)**:空间 / 项目 `pending_review → active → disabled`;加入申请 `knocking → accepted / rejected`。解决「审核流程要可追」的问题。对用户的意义是每一步都有据可查。
- **演示页 + 假内核**:忠实复刻平台判据(连它的 P0 一起复刻)。解决「真机上第一次调用就崩」的问题。对用户的意义是原型能在本机跑通、降低真机返工。
## 5. 机制
- **业务全在插件层、内核一字不动**:为什么这样设计——内核表是全租户共用的资产,动它会同步影响别人 ⇒ 给用户的结果是他的定制不牵动别人,坏了自己回滚。
- **分层:会话层 / 数据面 / 业务层三件分开**:`im-api.js` 只做会话(⛔ 不含业务语义)、`data-api.js` 只做数据面(⛔ 不直连 DB、不拼 SQL)、`spaces.js` 只做业务。为什么这样设计——平台缺陷修好后只动一处 ⇒ 给用户的结果是切换成本可控,不会「一改全烂」。
- **状态用追加事件而非改行**:为什么这样设计——平台房间维度表的 `update` / `remove` 恒 `bad-args`(平台缺陷) ⇒ 给用户的结果是**在缺陷还在的前提下仍然可用**,代价是表会一直长、读取要倒序取第一条。
- **归属房间一律取空间房间 id**:为什么这样设计——平台 `insert` 要求自带 `room_id` 且调用者是成员 ⇒ 挂在项目房间下的话申请人写不进申请单 ⇒ 给用户的结果是**申请闭环成立**(v2 的错就在挂错房间)。
- **读不到状态事件按最严处理**:为什么这样设计——平台可能没给跨主体读取口 ⇒ 给用户的结果是**宁可拦住,不放行**。
- **插件自己带假内核做演示**:为什么这样设计——没起实例时也要能验界面与契约 ⇒ 给用户的结果是界面在真机之前就能走查,减少真机轮次。
## 6. 强在哪、弱在哪
强者(多组,每组四行):
- 能力表现:业务与内核彻底解耦,全部业务语义集中在 `spaces.js` 一处。
- 在什么场景:平台数据面接口将来修正时。
- 相对谁:相对「业务逻辑散在路由里、与平台接口混在一起」的写法。
- 对用户什么结果:平台一改,插件只改一个文件,用户的既有数据不用动。
- 能力表现:自带假内核演示页,且把平台的 P0 也复刻进去。
- 在什么场景:原型阶段要给别人演示、或要在没起实例时验界面。
- 相对谁:相对「必须有真机才能演示」的做法。
- 对用户什么结果:走查不用等真机,省掉一轮轮上线。
弱者(多组,每组四行):
- 能力表现:管理员读不到「自己没加入」的空间的行,列不出全量。
- 在什么场景:管理员要做跨主体审核时。
- 相对谁:相对「管理员应有全局视角」的预期。
- 对用户什么结果:审核这件事在插件里做不完,得平台补一个跨主体读取口。
- 能力表现:停用只能落状态 + 界面拦截,服务端不强制。
- 在什么场景:被停用的人绕过界面直接调消息接口时。
- 相对谁:相对「停用即刻生效」的预期。
- 对用户什么结果:停用看着生效、实际没拦住,管理员以为自己管住了。
- 能力表现:无事务,补偿只做到「如实带回 id」。
- 在什么场景:一次操作里跨了两张表时。
- 相对谁:相对「写失败自动回滚」的做法。
- 对用户什么结果:可能出现半截状态,只能靠界面提示。
- 能力表现:`update` 恒失败这条平台缺陷要靠「追加事件表」绕。
- 在什么场景:任何一次状态变更。
- 相对谁:相对「平台接口正常」的理想情形。
- 对用户什么结果:表会持续增长,且平台修好后还要再切一次。
## 7. 对我们
**该借鉴**
- 机会点:分层切干净(会话层 / 数据面 / 业务层)。对应场景:平台接口将来变动。用户问题:改一处烂一片。它现在怎么做:三层互不越界,业务语义只在一处。建议方向:我们的包内也按模块分文件、每模块一个内核(`im-plugin-sdk.mjs` / `plugins-sdk.mjs` / `models-sdk.mjs` 已如此),继续保持。
- 机会点:声明文件里把实测结论写成注释。对应场景:后来人接手。用户问题:口径散失、踩同一个坑。它现在怎么做:`dsh.data.yaml` 顶部把三条平台硬判据与它的设计后果逐条写清。建议方向:**照搬这个习惯** —— 我们的 `dsh.data.yaml` 已经在顶部写了三条硬约束,继续。
- 机会点:插件自带假内核演示页。对应场景:没起实例时验界面。用户问题:必须有真机才能走查。建议方向:本产品的卡片刻可用同样的路子做演示态,减少真机轮次。
- 机会点:读不到状态按最严处理。对应场景:跨主体或状态不可读。用户问题:不该放行的被放行。建议方向:与我们的 fail-closed 一致(拿不到凭据一律拒),保持同向。
**该避开**
- 机会点:业务包自己造状态机来绕平台缺陷。对应场景:平台接口有硬伤时。用户问题:短期可用、长期背债。它现在怎么做:`state_event` 追加表绕 `update`。建议方向:我们的包要**避开造绕路**——遇到平台接口硬伤,先判断「这动作是不是该归平台进程」,若是就不进包(这正是我们六模块里 M1 被划出去的理由)。
- 机会点:演示用的假内核与真内核可能漂移。对应场景:真机第一次跑。用户问题:假内核过了、真机崩。建议方向:我们的包内门禁直接断言真实契约(`build.mjs` 逐字比对路径),不靠模拟件。
**可突破**
- 机会点:把「跨主体管理读取口」和「服务端强制停用」这类能力,收进一个统一的业务面。对应场景:管理员要管全局。用户问题:插件内做不到、平台又没给。它现在怎么做:记入对接单等平台补。建议方向:本产品的定位正好是「一个包把这类平台能力收拢」,这类缺口是我们最该优先解决的(但要注意:若动作要写平台库,它归平台进程那一半,⛔ 不能硬塞进包)。
@@ -0,0 +1,85 @@
# 竞品独立分析 · 官方 DSH 插件族(`subagent-local` 系列)
## 1. 它是谁、属哪一层、为什么纳入
- **是谁**:DSH(deepseek harness)官方自带的一批插件与插件基础设施,代表件是 `packages/subagent-local`(`subagent-local` 插件)与 `dsh-client-ui-settings-subagent`(它的设置页)。
- **属哪一层**:**直接竞品 + 点名参考实装**(第三层)。`@dsh-local/ai1net` 的 README 逐字点名它为参照实现。
- **为什么纳入**:用户要装 DSH 才能用我们的包,官方的插件形态就是他**默认已经拥有**的那一份。他为什么还要装我们的包,取决于我们比官方的做法多了什么。判断依据是用户的选择,不是官方的名气。
## 2. 用途
- 形态:**两端一套机制的插件组合包**(host 半 + client 半),随 DSH 一起分发。
- 给谁用:DSH 的终端用户,以及想给 DSH 加能力的插件作者。
- 干什么用:把一项能力(例如「派子 agent」)以插件形态装进宿主,出现在设置面板的插件区里,可列出、可安装、可移除、可更新、可检查更新。
- 证据等级:**L1–L2** —— 官方自述(`方案 §1.3` 引官方文档原文)+ 包内 README 引用的源码路径(`subagent-local/lib/client.js`)。⛔ 未见官方源码本体,本节之外的判断按此等级读。
## 3. 场景
- 进入方式:取不到:无源码、无界面实录,无法观察真实进入动作。
- 操作路径:取不到:同上。
- 核心步骤:取不到:同上。
- 系统帮了什么:部分可答 —— 官方文档原文说「独立插件窗口获得结构化的列出、安装、移除、更新和更新检查操作」,说明系统替用户做了全生命周期管理,用户不必手工放文件。
- 最终产出:取不到:同上。
- 哪一步最省力 / 最麻烦:取不到:同上。
**缺口**:本节六行里五行取不到,根因是**没有官方插件的运行实录**(本机只有我们的包和同族业务插件的源码,没有官方插件本体)。要补,需要有权限跑一次装了官方插件的 DSH 实例并录屏。本节不拿功能名罗列冒充使用过程。
## 4. 能力
每项按「是什么 → 解决什么问题 → 对用户起什么作用」写。
- **两端一套机制**:同一份代码,在 Web 组合与桌面组合里都能装。解决的是「同一能力要写两遍」的问题。对用户的意义是他换端不用重装、不用换习惯。
- **精确路径的服务端扩展点(`ctx.connection.fetch.register`)**:让插件能挂自己的 `/api` 逻辑。解决的是「插件没有服务端」的问题。对用户的意义是能力真的能跑起来,不只是张卡。
- **浏览器端封包(`dsh.client`)+ 槽位条目**:让插件能在设置面板里长出一张卡。解决的是「插件没地方露面」的问题。对用户的意义是能力可见、可操作。
- **插件全生命周期(列出 / 安装 / 移除 / 更新 / 检查更新)**:解决的是「装了之后怎么管」的问题。对用户的意义是他不必手工搬文件。
- **index 注入**:让插件能往宿主注入内容。解决的是「插件要改宿主呈现」的问题。
## 5. 机制
- **只认精确路径、不认前缀**:为什么这样设计——桌面壳的 host 走 fd 管道、不 listen,没有 `webServer`,路由只能按精确表匹配 ⇒ 给用户的结果是「同一份包两端都能跑」,代价是作者必须为目标每条路径都写死全路径。
- **浏览器端走 lazy-CJS 而非 ESM**:为什么这样设计——浏览器按经典脚本加载它,顶层 `import` 会直接 SyntaxError、整包 `import failed`、卡片根本不出现 ⇒ 给用户的结果是卡片稳定出现,而不是"看着是绿的其实没生效"。
- **`inject` 必须显式声明**:为什么这样设计——cordis 的服务只能靠 `inject` 拿,不声明就直接抛 ⇒ 给用户的结果是插件装载失败会**当场报错**,而不是静默 404。
- **官方不改主程序、扩展只走插件与注入点**:为什么这样设计——官方明写这是 developer preview,会有破坏性变更 ⇒ 给用户的结果是他的定制在官方升级时不会全量返工。
## 6. 强在哪、弱在哪
强者(多组,每组四行):
- 能力表现:两端扩展点由官方定义并实测对齐,插件作者只需照做。
- 在什么场景:用户要在服务器壳和桌面壳上用同一套能力时。
- 相对谁:相对「平台侧自己造一套界面」的做法。
- 对用户什么结果:装一次、两端一致,不会出现「桌面端没这个功能」。
- 能力表现:插件全生命周期由官方托管(列出 / 安装 / 移除 / 更新 / 检查更新)。
- 在什么场景:用户要装、要卸、要升级某个插件时。
- 相对谁:相对手工搬文件、手工改配置。
- 对用户什么结果:少掉一整类「改错文件、版本对不上」的麻烦。
弱者(多组,每组四行):
- 能力表现:只管单个插件,不做「多块业务能力收在一个包里」这件事。
- 在什么场景:用户要一次拿到一整套平台能力时。
- 相对谁:相对本产品(`@dsh-local/ai1net` 一个包六块模块)。
- 对用户什么结果:他得自己一个个装、一个个管,且各包版本互相不约束。
- 能力表现:不提供「平台进程那一半」的落脚点。
- 在什么场景:某项能力必须写平台库(例如创建隔离实例)时。
- 相对谁:相对平台侧内建的做法。
- 对用户什么结果:纯插件路线做不完平台的事,这部分要么不做,要么加进平台进程。
## 7. 对我们
**该借鉴**
- 机会点:两端扩展点交集这条约定。对应场景:跨服务器壳与桌面壳交付。用户问题:界面写一遍两端不通。它现在怎么做:官方定义交集(精确路径 + `dsh.client` + index 注入)并实测对齐。建议方向:**整条照搬,并把它写成包内门禁逐字断言的那几条**(我们已经在做,`build.mjs` 门禁 ①c–①h)。
- 机会点:lazy-CJS 封包形态。对应场景:浏览器端卡片加载。用户问题:卡片不出现且三条常规检查全绿。它现在怎么做:官方用 lazy-CJS,把外部依赖压进 factory 内 `require`。建议方向:照搬,并把「⛔ 零顶层 import/export/require」写成机械判据。
- 机会点:插件全生命周期托管。对应场景:安装 / 更新 / 卸载。用户问题:手工搬文件出错。它现在怎么做:官方提供结构化的列出 / 安装 / 移除 / 更新 / 检查更新。建议方向:**不重造**,把我们的包挂进这套机制(这正是上游件定的边界 1)。
**该避开**
- 机会点:分散单包。对应场景:用户要一整套能力时。用户问题:装多份、管多份、版本互不约束。它现在怎么做:官方各插件各管一摊。建议方向:不做成 N 个包,保持「一个发行单元」。
- 机会点:纯插件路线承平台动作。对应场景:要写平台库的动作用户场景。用户问题:动作落不了地。它现在怎么做:官方插件跑在实例内,够不到平台库。建议方向:承认分水岭,平台那一半加进平台进程,⛔ 不硬塞进包。
**可突破**
- 机会点:把「一个包 = 一个 pluginId = 一个库」做成跨端一致的默认形态。对应场景:用户跨端使用。用户问题:官方没规定业务能力的聚合方式。它现在怎么做:官方只管单插件形态。建议方向:用「包内分模块 + 表名分段 + 单入口按模块迁移」拿到「一次安装」又不丢「单独回滚一块」。
@@ -0,0 +1,86 @@
# 竞品独立分析 · 平台侧内建管理界面(不改插件,直接在平台进程里做)
## 1. 它是谁、属哪一层、为什么纳入
- **是谁**:不上插件这条路,直接把管理能力做在平台进程里 —— 用平台的 `webServer` 挂具名路由、支持 `exact` / `prefix` 两种匹配、还支持注册页面级路由,把管理页面直接加进平台站点。
- **属哪一层**:**间接替代**(第二层)。它不是另一个产品,是**同一个需求换一种做法**。
- **为什么纳入**:这是用户在「不做插件」时的默认退路。上游件明确记着:这条路今天就在用(管理面代码分布在平台 `src/web/routes/*`)。要说服用户走插件,必须先说清这条路差在哪。
## 2. 用途
- 形态:平台进程内的服务端路由 + 平台站点里的一张新页面,跟着平台一起发版。
- 给谁用:平台上的租户与管理员,通过访问平台站点使用。
- 干什么用:在平台站点里直接完成管理动作(看租户、管配置、看用量),不必装任何插件。
- 证据等级:**L3** —— 扩展点差异有实测出处(方案 §1.3 实测交集表,源 `apps/desktop-host/src/index.ts`、`dsh-client-connection/lib/index.js`);进程归属判定出处 `判定件 §3.12.3`。⛔ 未读到平台源码本体,具体页面清单不写。
## 3. 场景
- 进入方式:浏览器打开平台站点,进管理区。
- 操作路径:取不到:无平台界面实录,不逐步记录。
- 核心步骤:部分可答 —— 从「管理面代码分布在 `src/web/routes/*`」这条事实可知,动作是「打开页面 → 提交表单 → 平台进程直接处理 → 写平台库」。
- 系统帮了什么:平台进程有完整权限,能读写平台库,动作不受插件边界限制。
- 最终产出:数据落在平台库,页面刷新即见。
- 哪一步最省力 / 最麻烦:最省力的是**权限够、动作能做完**;最麻烦的是**桌面端用不了**——桌面壳没有 `webServer`,走这条路的能力在桌面端根本不存在。
**缺口**:无界面实录与源码,操作链只能从架构事实推。要补,需要一次平台站点管理页的走查。
## 4. 能力
- **服务端具名路由(`webServer`)**:让平台进程能挂任意服务端逻辑。解决「要写平台库」的问题。对用户的意义是这类动作**真的能做完**,不像插件那样只能做界面加请求。
- **`exact` / `prefix` 两种路径匹配**:解决「一整套 API 怎么组织」的问题。对用户的意义是路由写起来自由,不必为每条路径列全。
- **页面级路由**:能直接新增一张页面。解决「管理界面放哪」的问题。对用户的意义是他打开平台站点就能用,不用装东西。
- **`index` 注入**:能往站点注入内容。解决「要改平台呈现」的问题。
## 5. 机制
- **能力长在平台进程里**:为什么这样设计——平台进程对平台库有完整权限,管理动作天然属于它 ⇒ 给用户的结果是**动作能落地**,代价是这套能力**绑死在平台站点上**,换个端就没有。
- **跟平台一起发版**:为什么这样设计——代码在平台仓库里,走平台自己的发布流程 ⇒ 给用户的结果是版本一致、不会出现「插件与平台对不上」,代价是**改动影响所有租户**,一处出错全平台受影响。
- **走 `webServer` 而不是插件扩展点**:为什么这样设计——这是 Web 组合天生就有的东西,看起来最省事 ⇒ 给用户的结果是**服务器端能用**,但桌面端因为这个服务根本不存在,会停在 `pending (waiting for service: webServer)`。
## 6. 强在哪、弱在哪
强者(多组,每组四行):
- 能力表现:权限完整,能读写平台库,管理动作不受边界限制。
- 在什么场景:要创建隔离实例、要改租户归属、要动平台级配置时。
- 相对谁:相对插件(插件跑在实例内,够不到平台库)。
- 对用户什么结果:这类动作**能做完**,不必等平台开放新接口。
- 能力表现:改动随平台一次发版,两端(服务器 / 桌面)不会有版本差。
- 在什么场景:平台级策略调整时。
- 相对谁:相对「插件与平台版本各走各的、要对齐」的做法。
- 对用户什么结果:不会出现「平台是新的、插件是旧的」这种不一致。
弱者(多组,每组四行):
- 能力表现:桌面端没有 `webServer`,这条路的能力在桌面端完全不存在。
- 在什么场景:用户用桌面壳时。
- 相对谁:相对「只用两端交集」的插件做法。
- 对用户什么结果:桌面端要么没这个功能,要么他得回浏览器。
- 能力表现:改动影响所有租户,不分实例。
- 在什么场景:一次改动只该影响一个租户时。
- 相对谁:相对插件的「一插件一库、单独回滚」。
- 对用户什么结果:一处出错全平台受影响,回滚面大。
- 能力表现:能力与平台实现细节绑死,平台主程序一动就得跟着改。
- 在什么场景:官方 DSH 升级时。
- 相对谁:相对「只走官方插件与注入点」的做法。
- 对用户什么结果:定制会在升级时返工(官方明写这是 developer preview,会有破坏性变更)。
## 7. 对我们
**该借鉴**
- 机会点:管理动作的权限完整性。对应场景:要写平台库的动作。用户问题:插件做不到。它现在怎么做:把动作放在平台进程里。建议方向:**承认这条分水岭**——本产品里「要写平台库的那一半」就该长在平台进程,⛔ 不硬塞进包(上游件已把 M1 多租户的管理动作按这条划出去)。
- 机会点:`exact` / `prefix` 与页面级路由的自由度。对应场景:路由组织。用户问题:API 怎么排。建议方向:**只学它的思路、不学它的写法** —— 我们的包受桌面端约束只能用精确路径,这条自由度我们换不起。
**该避开**
- 机会点:把管理界面直接做在平台站点。对应场景:桌面用户要管自己的东西。用户问题:桌面端用不了。它现在怎么做:长在平台 `webServer` 上。建议方向:避开,改用两端交集(精确路径 + `dsh.client`),这正是本产品要解决的核心问题。
- 机会点:改动影响所有租户。对应场景:只该影响一个实例的改动。用户问题:一处错全平台受影响。建议方向:本产品的改动面天然窄(一实例一库),继续保持。
- 机会点:与平台实现细节绑死。对应场景:官方升级。用户问题:升级返工。建议方向:坚持只用官方插件与注入点(R2)。
**可突破**
- 机会点:把「管理能力」从「平台站点」搬到「两端一致的插件」。对应场景:用户跨端使用管理能力。用户问题:浏览器能用、桌面壳不能用。它现在怎么做:只能靠平台站点。建议方向:这就是本产品的核心价值,也是最该守住的差异 —— 任何新能力先问一句「桌面端有没有这个扩展点」,没有就不做。
@@ -0,0 +1,243 @@
# 1b · 竞品分析(汇总对比体)—— AI1NET 基础插件
> 体例:本份是**汇总对比体**(全池一份)。单个竞品的独立分析见 `1b-独立分析/` 目录,每个一份。两份体例齐备才算 1b 完成。
> 口径:只讲**用途 / 场景 / 功能 / 作用 / 优势**五问,其余与产品规划无关的内容不展开。
---
## 1. 分析目标与范围
**本次要回答的问题**:用户要拿到「一整套平台业务能力」,今天有哪几条路可走?竞品各自做到了哪一步?本产品该学什么、避开什么、突破什么?
**五问落点**:
| 五问 | 落点 |
|---|---|
| 用途:它是什么、给谁用、干什么用 | §3 |
| 场景:用户在什么处境下会用它 | §4 |
| 功能:它有哪些核心能力 | §5 |
| 作用:每项能力解决什么问题 | §5 |
| 优势:它相对谁、在哪些场景下更强或更弱 | §7 |
**本次不展开**:竞品的内部实现细节、性能数值、商业定价(本产品是自用形态,不涉及售卖)。
**竞品池(4 个)**:
| # | 竞品 | 层级 | 为什么是它 |
|---|---|---|---|
| 1 | 官方 DSH 插件族(`subagent-local` 系列) | 直接竞品 + **点名参考实装** | 用户装了 DSH 就默认拥有它;`@dsh-local/ai1net` 的 README 逐字点名它为参照实现 |
| 2 | `dsh-plugin-mcn-suite` | 直接竞品 | 同一台机器、同一套投放机制、同一份数据面规范下**已经跑通**的业务插件包 |
| 3 | `@dsh-local/dsh-plugin-partment`(空间与项目) | 直接竞品 | 代表「一块能力一个包」这条路的已完成态,全源码在机 |
| 4 | 平台侧内建管理界面 | 间接替代 | 用户在「不做插件」时的默认退路,今天就在用 |
**点名参考实装已收录**:第 1 项。它在 §3–§10 每一节与其它竞品同列参与横向对比,不单独成节。
---
## 2. 竞品选择与范围
分水岭是**用户的选择**,不是名气:用户要「一次拿到一整套平台能力」时,会在这四条路里选一条。
- **选 1(官方插件族)** 的用户处境:他已经装了 DSH,会先看官方给了什么。官方的做法是**一个能力一个插件**,各自独立。
- **选 2(mcn-suite)** 的用户处境:他要在实例里跑一块具体业务(内容工作台)。它证明「业务能力做成插件」这条路在本平台是通的、有版本与回滚链的。
- **选 3(partment)** 的用户处境:他要一块**带协作与归属**的业务能力,且不想动内核。它证明「业务全在插件层、内核一字不动」可行。
- **选 4(平台侧内建)** 的用户处境:他不想装插件,只要打开平台站点就有。这条路今天覆盖了管理面的一部分,代价是桌面端用不了。
⚠️ **同族但不单列**:`@dsh-local/carbon`(把宿主侧 Carbon MCP 端点的工具面接进实例的最小桥)不纳入池子 —— 用户不会在它和本产品之间做选择,它不是一个「拿到全套能力」的选项。它只作为「本平台还有别的插件包」的背景存在。
---
## 3. 竞品用途
| 竞品 | 是什么形态 | 服务谁 | 拿它干什么用 |
|---|---|---|---|
| 官方 DSH 插件族 | 两端一套机制的插件组合包 | DSH 终端用户与插件作者 | 把一项能力装进宿主,出现在设置面板插件区,可列出 / 安装 / 移除 / 更新 |
| `dsh-plugin-mcn-suite` | 业务插件包(host + client + 独立库) | 平台上的内容运营者 | 管账号、拉视频、做分析、记创作 |
| `dsh-plugin-partment` | 业务插件包(host + client + 独立库) | 平台普通用户与管理员 | 建空间、建项目、申请加入、群聊、审核启停 |
| 平台侧内建管理界面 | 平台进程内的服务端路由 + 站点页面 | 租户与管理员 | 打开平台站点直接完成管理动作,不装插件 |
---
## 4. 使用场景横向对比
按用户处境横向铺开。每行写「用户要办成什么」,再写各家怎么做。
**场景 1 · 用户第一次装好 DSH,要拿到一整套平台能力**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | 一个个装:按需装各自要的插件,各插件各管一摊 |
| mcn-suite | 一次装一个业务包,只覆盖内容工作台那一块 |
| partment | 一次装一个业务包,只覆盖空间与项目那一块 |
| 平台侧内建 | 什么都不装,打开平台站点就用 |
| **本产品** | 装官方 DSH + 一个包,六块模块一次到位 |
**场景 2 · 用户要在桌面壳里管自己实例的东西**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | 官方插件走两端交集,桌面端能用(这是它最强的一处) |
| mcn-suite | 走 host 精确路由 + client 卡片,桌面端理论可用 |
| partment | 同上 |
| 平台侧内建 | ⛔ **桌面端做不到** —— 桌面壳没有 `webServer`,会停在 `pending (waiting for service: webServer)` |
| **本产品** | 包本身就是按两端交集造的,桌面端与服务器壳同一份 |
**场景 3 · 用户要存业务数据,且不想污染平台库**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | ⛔ 这一层官方不管(官方只管插件形态) |
| mcn-suite | 走插件数据面:独立库 + `dsh.data.yaml` 声明 + 平台侧执行器建库,台账可见 |
| partment | 同上,五张表全走 `scope: room` 的归属隔离 |
| 平台侧内建 | 数据直接落平台库 |
| **本产品** | 一个包一个库 `dshs_pl_ai1net`,表名带模块段,六块共库但可单块回滚 |
**场景 4 · 升级坏了要退回去**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | 官方托管更新与更新检查,用户不必手工搬文件 |
| mcn-suite | 共享只读包库投放,每次 share 自动落 tgz,回滚素材四份在位 |
| partment | 未见投放记录(`schemaVersion` 仍为 1,从未建库 ⇒ 未投放) |
| 平台侧内建 | 跟随平台发版,没有「单个能力回滚」这回事 |
| **本产品** | 一个包一个版本 ⇒ 改一块要重发整包(这是「聚合」的代价,明写在取舍里) |
**场景 5 · 用户要一个管理动作真的落地(例如创建隔离实例)**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | ⛔ 做不到 —— 插件跑在实例内,够不到平台库 |
| mcn-suite | ⛔ 不做这类动作 |
| partment | ⛔ 做不到,管理员跨主体读取这一条已记入对接单等平台补 |
| 平台侧内建 | ✅ 能做 —— 平台进程权限完整 |
| **本产品** | 拆两半:界面 + 请求在实例内,**动作加进平台进程**(⛔ 不由插件实现) |
**场景 6 · 第三方作者要把自己的能力接进来**
| 竞品 | 怎么做 |
|---|---|
| 官方 DSH 插件族 | 官方定义扩展点交集,作者照做 |
| mcn-suite | 未见对外 SDK |
| partment | 未见对外 SDK |
| 平台侧内建 | 不适用(没有第三方接入面) |
| **本产品** | 包内挂三套 SDK(IM / 插件 / 模型),`exports` 已对外 |
---
## 5. 功能横向对比
维度按本产品品类自定(可增不可缺)。每个维度都接「解决什么问题 / 起什么作用」。
| 维度 | 官方 DSH 插件族 | mcn-suite | partment | 平台侧内建 | 解决什么问题 / 起什么作用 |
|---|---|---|---|---|---|
| 打包粒度 | 一能力一插件 | 一业务一套包 | 一业务一套包 | 不打包 | 解决「一次装多少」——决定用户要装几次、要管几次 |
| 跨端一致 | ✅ 两端交集 | ⚠️ 未见桌面端验证 | ⚠️ 同上 | ⛔ 只有 Web | 解决「桌面壳能不能用」——决定能力覆盖到哪些端 |
| 服务端扩展点 | `connection.fetch.register` 精确路径 | 精确路由(`/mcn/api/*`) | 精确路由 | `webServer` 具名路由 + 前缀 + 页面路由 | 解决「插件有没有服务端」——决定功能是不是真的能跑 |
| 客户端露面 | `dsh.client` + 槽位条目 | client 半出界面 | 侧边栏 + 详情页 | 站点页面 | 解决「能力在哪被看见」——决定用户找不找得到 |
| 数据面 | 官方不管这一层 | 独立库+声明+台账 | 独立库+声明(五表) | 平台库 | 解决「数据往哪放」——决定隔离性与回滚面 |
| 权限与身份 | `inject` 显式声明 | 每插件 id 头 | 归属房间隔离 | 平台进程权限 | 解决「谁能做什么」——决定越权挡不挡得住 |
| 单例与并发 | 官方不规定 | 未见 | 无事务 | 不适用 | 解决「同一件事做两次」——决定会不会吃光额度或半截状态 |
| 生命周期管理 | 官方托管(列出/装/卸/更新/查) | 共享层投放 + 回滚素材 | 未投放 | 随平台发版 | 解决「装了之后怎么管」——决定升级与回退顺不顺 |
| 对外 SDK | 官方扩展点即接口 | 无 | 无 | 无 | 解决「第三方怎么接」——决定生态能不能长 |
| 平台动作承载 | ⛔ 不能 | ⛔ 不做 | ⛔ 不能(已记对接单) | ✅ 能 | 解决「要写平台库的动作归谁」——决定分水岭在哪 |
---
## 6. 产品机制与交互方式
- **精确路径 vs 前缀路由**:官方与同族包都用精确路径,因为桌面壳只认精确匹配;平台侧内建能用前缀,因为它只在 Web 组合里跑。⇒ **为什么这样设计**:能力要跨端就必须换掉最省事的那种写法。**给用户的结果**:能力在两端都在,代价是每条路径要写全。
- **lazy-CJS 客户端封包**:浏览器按经典脚本加载插件,顶层 `import` 会让整包加载失败、卡片根本不出现。⇒ **为什么这样设计**:这是唯一能在浏览器里跑起来的形态。**给用户的结果**:卡片稳定出现。
- **一个包一个库**:库名从包名推,表在库里按模块分段。⇒ **为什么这样设计**:插件没有平台库权限,只能有自己的库。**给用户的结果**:包与包互不干扰;同一包内多块共库,靠表名分段保住单块回滚。
- **fail-closed 的凭据校验**:带身份头却没带凭据一律拒,不回退到本机 env。⇒ **为什么这样设计**:不回退,插件就没法冒充别人。**给用户的结果**:拿不到凭据时是「不能用」,不是「悄悄用了别人的身份」。
- **状态用追加事件(partment 的做法)**:平台房间维度表的 `update` / `remove` 恒 `bad-args`,改不了行。⇒ **为什么这样设计**:缺陷还在时的唯一可行解。**给用户的结果**:可用,但表会持续增长,平台修好后还要再切一次。
- **管理动作拆两半(本产品的做法)**:界面与请求在实例内,要写平台库的动作加进平台进程。⇒ **为什么这样设计**:平台不是实例,装不了插件。**给用户的结果**:该能做的都能做,但「一个包」的准确含义是「一个发行包,两个进程各加载一部分」。
---
## 7. 优势与不足
每条按「能力表现 × 使用场景 × 对比对象 × 用户价值」写。
- 官方 DSH 插件族**强在**两端交集(相对平台侧内建),在「用户用桌面壳」这个场景下,桌面端功能完整可用 ⇒ 用户不必为了一个功能换回浏览器。**弱在**只管单插件(相对本产品),在「一次拿一整套」这个场景下要装多次、各包版本互不约束 ⇒ 用户管理成本高。
- mcn-suite **强在**投放与回滚链完整(相对 partment,后者未投放),在「一次给多实例上线」这个场景下上线与回退都有据可查 ⇒ 出问题能退。**弱在**只管自己那一摊(相对本产品),在「同时管模型 / IM / 插件 / 设备接入」这个场景下用户要一个个插件找过去 ⇒ 入口分散。
- partment **强在**业务与内核彻底解耦、分层干净(相对 mcn-suite,后者未见分层),在「平台接口将来修正」这个场景下只改一处 ⇒ 既有数据不动。**弱在**有硬缺口(相对平台侧内建),在「管理员跨主体审核」与「停用即刻生效」这两个场景下做不到 ⇒ 管理员以为自己管住了,其实没管住。
- 平台侧内建 **强在**权限完整、动作能做完(相对所有插件方案),在「创建隔离实例、改租户归属」这个场景下不受边界限制 ⇒ 这类动作真的落地。**弱在**桌面端不存在(相对官方插件族与本产品),在「用户用桌面壳」这个场景下完全不可用 ⇒ 用户只能回浏览器。
- 本产品 **强在**「一个包一次到位」+「跨端一致」(相对上面每一条),在「跨端使用且要一次装齐」这个场景下装一次、两端一致、更新只更一个包 ⇒ 用户的安装与管理成本最低。**弱在**一个包一个版本(相对「一块一个包」),在「只改一块」这个场景下要重发整包 ⇒ 更新颗粒度粗,且六块共库,一次迁移失败牵动全部。
---
## 8. 竞品能力矩阵
| 能力 / 场景 | 官方插件族 | mcn-suite | partment | 平台内建 | 机会 |
|---|---|---|---|---|---|
| 跨端一致(桌面壳可用) | ✅ | ⚠️ | ⚠️ | ⛔ | 行业共识方向,但只有官方与本产品做到 |
| 服务端逻辑(精确路径) | ✅ | ✅ | ✅ | ⛔(用前缀) | 已是基础能力 |
| 一次装齐整套能力 | ⛔ | ⛔ | ⛔ | 不适用 | 🔴 **无人做好** —— 本产品的核心机会 |
| 数据面独立隔离 | 不涉及 | ✅ | ✅ | ⛔ | 已是基础能力(同族包都有) |
| 投放 / 回滚链 | ✅(官方托管) | ✅(四份回滚素材) | ⛔(未投放) | ⛔(随平台) | 基础能力,但覆盖不均 |
| 管理动作落地(写平台库) | ⛔ | ⛔ | ⛔ | ✅ | 天然分水岭,插件侧**普遍做不到** |
| 对外 SDK | ✅ | ⛔ | ⛔ | ⛔ | 普遍短板 |
| 单例 / 并发治理 | 不规定 | ⛔ | ⛔ | 不适用 | 普遍短板 |
| 分层解耦(平台改动影响面) | 不涉及 | ⚠️ | ✅ | ⛔ | 普遍做得不好 |
| 包源码可追溯 | ✅(官方仓) | ⛔(未跟踪目录+散在 `D:/dshworkspace`) | ✅(在本机工作区) | ✅ | 普遍做得不好 |
**矩阵读出的五件事**:
1. **行业共识能力**:服务端精确路径、客户端露面、独立数据面 —— 同族包都有,不再是差异点。
2. **竞品之间的差异能力**:跨端一致(只有官方与本产品做到)、分层解耦(只有 partment 做得透)。
3. **某家的独有能力**:平台侧内建的「权限完整、动作能做完」;mcn-suite 的「投放回滚链完整」。
4. **普遍做得不好的能力**:**一次装齐整套能力(无人做好)**、对外 SDK(只有官方有)、单例与并发治理、包源码可追溯。
5. **还没被解决好的需求**:管理动作跨「实例」与「平台」两个进程这件事,所有插件方案都做不到 —— 而这正是本产品要拆两半解决的那一件。
---
## 9. 可借鉴点与产品机会
**该借鉴**(每条追回 §4 / §5 / §7)
- 机会点:两端扩展点交集(精确路径 + `dsh.client` + index 注入)。对应场景:§4 场景 2。用户问题:桌面端用不了。竞品现状:官方已验证有效(§5 跨端一致)。建议方向:整条照搬并写成包内门禁。
- 机会点:lazy-CJS 客户端封包。对应场景:§4 场景 2。用户问题:卡片不出现且常规检查全绿。竞品现状:官方这么做。建议方向:照搬,加机械判据。
- 机会点:一插件一库 + `dsh.data.yaml` 声明 + 台账。对应场景:§4 场景 3。用户问题:数据往哪放、怎么隔离。竞品现状:mcn-suite 与 partment 都用(§5 数据面)。建议方向:照搬。
- 机会点:投放时自动落回滚素材。对应场景:§4 场景 4。用户问题:升级坏了退不回去。竞品现状:mcn-suite 四份回滚包在位(§7)。建议方向:照搬,收口清单固定这一条。
- 机会点:分层切干净(会话层 / 数据面 / 业务层)。对应场景:§4 场景 5。用户问题:平台一改烂一片。竞品现状:partment 做得透(§7)。建议方向:包内按模块分文件、每模块一个内核。
**该避开**
- 机会点:把管理界面做在平台站点上。对应场景:§4 场景 2。用户问题:桌面端做不到。竞品现状:平台内建只能用 Web(§6)。建议方向:只用两端交集。
- 机会点:造状态机绕平台缺陷。对应场景:§4 场景 5。用户问题:短期可用、长期背债。竞品现状:partment 用 `state_event` 绕 `update`(§6)。建议方向:先判断这动作该不该归平台进程,该归就不进包。
- 机会点:包源码不受版本管理。对应场景:§4 场景 4。用户问题:说不清某版改了什么。竞品现状:mcn-suite 源码在版本库里是未跟踪目录(§8 矩阵)。建议方向:保持源码可追溯,每次出包留 sha256。
- 机会点:共享层刷新与实例生效之间的版本窗口。对应场景:§4 场景 4。用户问题:以为升级了其实没升。竞品现状:mcn-suite 真机实测出现过(独立分析 §6)。建议方向:把「当前实际载的是哪一版」做成可见读数。
**可突破**
- 机会点:一个包一次拿齐整套能力。对应场景:§4 场景 1。用户问题:装多次、管多次。竞品现状:**无人做好**(§8 矩阵)。建议方向:保持「一个发行单元 + 包内分模块 + 表名分段 + 单入口按模块迁移」,这是本产品最明确的差异。
- 机会点:管理动作拆两半(实例侧界面 + 平台侧动作)。对应场景:§4 场景 5。用户问题:所有插件方案都做不到。竞品现状:普遍的空白(§8 矩阵)。建议方向:这是最该突破的一处,但要注意「平台进程不能装插件」这条硬事实。
- 机会点:对外 SDK。对应场景:§4 场景 6。用户问题:第三方没法接。竞品现状:只有官方有(§8 矩阵)。建议方向:包内三套 SDK 已是差异点,把「SDK 要稳」写成约束。
---
## 10. 结论(产品层)
- **用户最核心的需求**:装一次、两端都能用、要管的东西在一个地方 —— 而不是装 N 个包、各找各的入口、桌面端还用不了。
- **竞品共同解决了什么**:单块业务能力做成插件这件事已经通了(服务端精确路径、客户端露面、独立数据面、投放回滚),同族包里都有实例。
- **竞品共同存在什么问题**:只解决「一块」,不解决「一整套」;管理动作跨实例与平台两个进程这件事,插件方案普遍做不到;对外 SDK 与并发治理普遍缺;包源码可追溯普遍做得不好。
- **哪些能力已经是基础能力**:精确路径的服务端逻辑、客户端卡片露面、独立数据面、投放与回滚 —— 这些不构成差异。
- **哪些能力还能形成差异**:一次装齐整套能力、跨端一致、管理动作跨进程拆两半、对外 SDK。前两条本产品已经在做,后两条是还没做完的。
- **本产品应优先解决什么**:**先守住「一个包一次到位 + 跨端一致」这条已有的差异**(这是相对池子里所有竞品最明确的一处),再补「管理动作拆两半」与「对外 SDK 稳定」这两处空白。
**一句话回答 §0.3 的完成判据**:竞品已经能把一块能力做成插件(学它的契约与数据面做法);它们都没做好「一整套能力一次到位」,也没解决「管理动作跨两个进程」;本产品该学契约与数据面、避开平台侧内建那条路、突破「一次装齐 + 跨端一致 + 动作拆两半」。
---
## 附:输出检查
- [x] §1 把本次目标与竞品池写死在开头,五问各有明确落点
- [x] 竞品池三层齐全(直接竞品 3 + 间接替代 1),点名参考实装已收录并标明层级
- [x] §4 说清「用户什么时候、为什么用」,并写出走通的路径(partment 与 mcn-suite 有实录或源码支撑,纯推断处已标缺口)
- [x] §5 每个维度都接了「解决什么问题 / 起什么作用」
- [x] §6 每条机制都接了「为什么这样设计 ⇒ 给用户什么结果」
- [x] §7 每条判断都写明了「相对谁、在什么场景、什么结果」
- [x] §8 矩阵取的是能区分竞品的行,看得出共识 / 差异 / 独有 / 短板 / 未解决需求
- [x] §9 每一条都能追回 §4 / §5 / §7
- [x] 全文只围绕用途 / 场景 / 功能 / 作用 / 优势展开
- [x] §10 结论只落在产品层,并可一句话回答 §0.3
@@ -0,0 +1,128 @@
# 1c · 用户画像 —— AI1NET 基础插件
> 三条画像,覆盖三种角色。每条结论标注来源:`【事实】`=有源码 / 单据 / 用户原话支撑;`【推演】`=从架构事实推断,**不得当作 1d 的依据**。
> 数据来源:包内源码与 README、`交付物/` 各单据、同族插件源码、上游件的用户原话。
> 数据缺口:**没有一条真实访谈记录**。本份全部结论来自「产物反推」与用户原话,按用研等级只算「弱证据」。要升到强证据,需要一次对三类角色的直接访谈。
---
## 画像一 · 实例使用者(租户)
**基本信息**
- 化名:陈岚,30 岁上下,AI1NET 平台上的一个实例用户。她在自己的实例里干活,不负责平台运维。
- 关键特征:懂业务、懂工具,但**不碰命令行**。她的判断标准只有一个——「我要的东西能不能点到」。
- 来源:`【推演】`(依据:五张卡片的形态说明,这套界面是为「点得到」而设计的)。
**主要「要办的事」**
- 在自己的实例里,把**模型、插件、IM、设备接入**这几摊都管起来——换模型、启停插件、开会话、配对设备。
- 处境:每次要动其中一摊的时候。频率按需,可能一天几次,也可能一周一次。
**三条主要痛点**
1. **入口分散**(影响:每次都要重新找)。这几摊分属不同插件包,每包的入口位置与风格各不一样。来源:`【事实】`(`1b-竞品分析.md §8` 矩阵——同族包各管一摊)。影响程度:中。
2. **有的能力没有界面**(影响:干脆做不了)。多租户与覆盖网络这两块只有数据面表,界面还没接。来源:`【事实】`(包内 `dsh.data.yaml` 有 `tenant_*` / `net_*` 表,客户端只有五张卡)。影响程度:高。
3. **桌面壳与浏览器两套体验不一致**(影响:得换工具)。平台侧内建的能力在桌面壳里不存在。来源:`【事实】`(`1b-独立分析/平台侧内建管理界面.md §6`)。影响程度:中。
**三个想要的结果**
1. 打开一处就能看到自己要管的东西。衡量方式:从「要管某一摊」到「打开对应界面」之间不超过一步。
2. 该有界面的能力都有界面,不必因为「没做界面」而放弃。衡量方式:六块模块里,能点的块数。
3. 换端不用换习惯。衡量方式:桌面壳与浏览器里能做同一批事。
**一条和直觉相反的发现**
- 直觉是「用户要功能多」。从证据看,**用户更在意「少装东西、少找入口」**——上游件的用户原话问的是「能不能放到**一个**插件中」(`【事实】`:2026-09-26 13:0x 原话),问的是聚合,不是能力条数。
- 为什么影响产品决策:它把第一版的优先级从「多接几块」拉到「把已有的几块收进同一个入口」。这条支持了 `1a` 的 A6(第一版=已落地的四块)与 A9(一个面板五张卡)。
**产品契合度**
- 接得住:五张卡片挂在同一个设置面板下,入口问题解决;跨端一致由「两端交集」这条约束保证。
- 摩擦点:多租户与覆盖网络两块只有表、没有界面,这个画像的第一个结果**现在给不了**。
- 没满足的地方:设备接入默认不启(`【事实】`:`1a` 待复核清单第 12 条),用户得自己打开,且包内没有「怎么开」的显式引导。
---
## 画像二 · 第三方插件作者
**基本信息**
- 化名:周珩,独立开发者,想把自己的能力接进 DSH 生态。
- 关键特征:会写代码,不熟悉这套平台的内部约定。他最怕的不是写不出来,是**写完了才发现方向不对**。
- 来源:`【推演】`(依据:包内三套 SDK 的 `exports` 已对外,说明 SDK 是给外人用的)。
**主要「要办的事」**
- 用包内 SDK 把自己的能力接进 IM / 插件 / 模型这三套机制,且**不重造轮子**。
- 处境:他决定「接入一次」那一刻。频率低,但代价高——接错了要重写。
**三条主要痛点**
1. **契约不可见**(影响:每次都要猜)。扩展点只在代码与注释里,没有一个「照做就行」的对外说明。来源:`【事实】`(包内 README 与门禁承担了契约说明的职责,但那是给包内维护者的)。影响程度:高。
2. **身份与凭据规则容易踩坑**(影响:功能静默不可用)。带身份头不带凭据一律拒,不回退;这条规则不显然。来源:`【事实】`(README「残留①」+ `index.js::presentedOf` 的三种取值语义)。影响程度:高。
3. **SDK 可能随包版本变动**(影响:升级即返工)。一个包一个版本,SDK 与业务模块同包发布,没有独立的兼容承诺。来源:`【事实】`(`package.json` 的 `dshCompat` 约束的是 DSH 版本,不是 SDK 版本)。影响程度:中。
**三个想要的结果**
1. 有一份能照着做的接入说明,不必读源码。衡量方式:从零接一次,需要读源码的次数。
2. 接入后行为可预测——该拒的拒、该通通的,不出现「看着像没人调」的静默失败。衡量方式:失败时能不能拿到具名的原因。
3. 升级不返工。衡量方式:包升级后自己的代码要不要改。
**一条和直觉相反的发现**
- 直觉是「作者最需要的是更多能力」。从证据看,**作者最需要的是「可预测」**——三层取值语义(没带身份头 / 带了头没带凭据 / 带了凭据)必须分清(`【事实】`:`index.js` 注释逐条写明),因为分不清就出静默失败。
- 为什么影响产品决策:SDK 的稳定性与「失败要具名」这件事,优先级高于 SDK 的功能广度。这条支持 `1a` 的 B4(失败要具名映射)。
**产品契合度**
- 接得住:三套 SDK 已挂 `exports`;失败路径都有具名 `reason` 与具名 HTTP 码。
- 摩擦点:没有一份**对外的**接入说明文档;`dshCompat` 只约束 DSH 版本,不约束 SDK 版本。
- 没满足的地方:SDK 的版本承诺与兼容窗口没有明说。
---
## 画像三 · 平台运维 / 交付负责人
**基本信息**
- 化名:吴敏,负责平台侧的上线、版本与回滚。她要对「线上跑的是哪一版、坏了怎么退」负责。
- 关键特征:她的判断标准是「出事时我能不能三分钟内说清现状」。她不在乎功能多,在乎**可追溯**。
- 来源:`【事实】`(`交付物/MCN数据面接入-*` 各单据里逐票记录版本、包大小、sha256、回滚素材位置,这就是她的工作产物)。
**主要「要办的事」**
- 把一块能力安全地投到多个实例上,并保证随时能退回去。
- 处境:每次投放、每次实例出问题时。频率:按投放节奏。
**三条主要痛点**
1. **共享层已更新、实例还载旧版**(影响:她可能误报「已升级」)。真机实测出现过:共享层 0.4.0、实例仍载 0.3.15,要重启才生效。来源:`【事实】`(`交付物/MCN数据面接入-阶段一-20260925.md` S9-附 与阶段二 P8)。影响程度:高。
2. **包源码不在版本管理里**(影响:说不清某版改了什么)。同族包的源码在 `D:/dshworkspace` 里是未跟踪目录。来源:`【事实】`(`MCN数据面接入-阶段二-20260925.md` 未闭合项 4)。影响程度:中。
3. **投递顺序是硬约束、错了静默无数据面**(影响:功能看着装了其实没数据面)。先建库再投放;`package.json` 漏写 `dsh.data.schema` 就等于没有数据面。来源:`【事实】`(README「数据面」节逐条写明)。影响程度:高。
**三个想要的结果**
1. 一眼看清每条线上跑的是哪一版。衡量方式:能不能用一个读数回答,而不是翻日志猜。
2. 每次投放都有可回滚的素材。衡量方式:回滚包在不在位。
3. 顺序错了会报错,不会静默通过。衡量方式:漏一步时,是报错还是「看着成功」。
**一条和直觉相反的发现**
- 直觉是「运维最怕宕机」。从证据看,**她最怕的是「看着成功」**——共享层显示已更新、台账显示 ready,而实例跑的还是旧代码(`【事实】`:真机实测读到的两个版本并存的局面)。
- 为什么影响产品决策:任何「改完了」的声明都必须落到进程级或文件级读数,不能只看回显。这条支持 `1a` 的 B5(数据契约与顺序硬约束)与我们收口时必做的「回滚素材在位」检查。
**产品契合度**
- 接得住:`dsh.data.yaml` 声明 + 平台侧台账(`state` / `schema_version` / `last_error`)提供了可读的状态面。
- 摩擦点:「实例当前实际载的是哪一版」这个读数不在包的控制范围内,包能做的是把自己的版本号写进响应(已有:探针路由回 `skeleton` 与各模块版本号)。
- 没满足的地方:包内没有一份「投放前检查清单」,把「先建库再投放」「回滚素材在位」这类顺序约束固化成可执行步骤。
---
## 数据缺口(标出来)
1. **零真实访谈**。三条画像全部由产物反推,证据等级为「弱」,不满足用研强度要求。要升强度,需要对三类角色各做一次访谈,只问已发生的事(最近一次是什么时候、上次怎么处理的、当时最费劲的是哪一步)。
2. **「陈岚」的痛点排序未经她本人确认**——痛点 1/2/3 的严重度是我按「能不能点到」这条标准推的。
3. **「周珩」是否真实存在**未验证:三套 SDK 对外挂出只说明「设计上给外人用」,不说明今天真有第三方作者。
4. **「吴敏」的角色是真的**(交付单据即其产物),但她的三条痛点严重度未经她排序确认。
@@ -0,0 +1,194 @@
# 1d · 产品策略 —— AI1NET 基础插件
> 九节画布。每条结论都标来源:追到 `1a` / `1b` / `1c` 的哪一处,或标 `【假设】`。
> ⚠️ 本份不得引用 `1c` 里标 `【推演】` 的条目当依据(按 `1a` 的硬约束)。
---
## 1. 愿景
**靠什么打动人**:装一次,两端都能用。
**想做成的样子**:用户装官方 DSH,再加这一个包,就拿到平台的全套业务能力。他不必知道背后有几个进程、几个模块、几个库;他只知道「我的东西都在这一个地方」。
**坚持什么**:
- **只有两端都存在的扩展点才用**(来源:`1a` A13)。
- **一个包就是一次安装、一个版本**(来源:`1a` A2)。
- **失败要具名,不静默**(来源:`1a` B4;`1c` 画像二与画像三的两条反直觉发现都指向这里)。
---
## 2. 市场切分
按**用户遇到的问题**切,不按人口统计切。切出三个:
**切分 A · 要一次装齐的人**
- 要办的事:拿到一整套平台能力,不想装 N 个包、管 N 个版本。
- 想要的结果:装一次、入口一处、更新只更一个包。
- 限制条件:他可能是桌面壳用户,也可能是服务器壳用户。
- 为什么先切这一拨:这是 `1b §8` 矩阵里**无人做好**的那一格,也是用户原话直接问出来的那一件(`1a` A1 的`【事实】`来源)。
**切分 B · 要跨端一致的人**
- 要办的事:在桌面壳和浏览器里做同一批事。
- 想要的结果:换端不换习惯。
- 限制条件:桌面壳没有 `webServer`,能力必须只用两端交集。
- 为什么这一拨:`1b §7` 显示,池子里只有官方插件族与本产品做到跨端一致,是少数派能力。
**切分 C · 要把能力接进来的插件作者**
- 要办的事:用包内 SDK 接自己的东西,不重造轮子。
- 想要的结果:契约清楚、行为可预测、升级不返工。
- 限制条件:他读不到包内维护者的上下文。
- 为什么这一拨:`1b §8` 矩阵里「对外 SDK」是普遍短板,只有官方有。这一拨现在没有对应供给。
---
## 3. 相对成本
**走独特价值,不走低成本。**
理由:本产品是自用形态的基础设施,不比谁便宜(`1a` A2 的成功衡量里没有成本项)。它的成本在**维护**端:一个包一个版本,改一块要重发整包(`1a` A7 与 `1b §7` 都记着这个代价)。维护成本省不下来,那就别在别处省了,把力气全投到「两端一致」和「契约清楚」这两件上。
**相对竞品的位置**:
- 相对「一模块一包」(mcn-suite / partment 那条路):我们的安装与升级成本更低,但更新颗粒度更粗。
- 相对「平台侧内建」:我们的桌面端覆盖更广,但权限更小、动作做不完。
- 相对「官方插件族」:我们的聚合度更高,但契约自由度更低(只能用精确路径)。
---
## 4. 价值主张
**切分 A · 要一次装齐的人**
- **之前**:装多个包,各包入口位置与风格不一样,各包版本互不约束(来源:`1b §8` 矩阵「一次装齐无人做好」)。
- **怎么做**:一个发行包,包内分六块模块;表名带模块段,靠单入口按模块迁移保住「单独回滚一块」(来源:`1a` A6 / B5)。
- **之后**:装一次就有全套;要回滚某一块时能单独回。
- **替代**:继续用「一块一个包」的做法(mcn-suite / partment 那条路)。
**切分 B · 要跨端一致的人**
- **之前**:桌面壳里用不了平台站点上的管理能力,会停在 `pending`(来源:`1b §7`)。
- **怎么做**:只用两端都存在的扩展点——`connection.fetch.register` 精确路径 + `dsh.client` + index 注入(来源:`1b §6`)。
- **之后**:桌面壳与服务器壳装同一个包,做同一批事。
- **替代**:回浏览器做(平台侧内建那条路)。
**切分 C · 要接能力的插件作者**
- **之前**:只能读源码猜契约(来源:`1c` 画像二痛点 1)。
- **怎么做**:包内三套 SDK 已挂 `exports`;失败路径一律具名 `reason` 映射具名 HTTP 码(来源:`1a` B4 / B6)。
- **之后**:照着接一次就行;失败时能拿到具名原因,不必猜。
- **替代**:照抄官方 `subagent-local` 的写法,或干脆不接。
---
## 5. 取舍
**明确不做什么**(来源:`1a` A7):
- ⛔ 不起实例 —— 归部署方案(systemd / K8S 随部署选)。
- ⛔ 不取身份、不把自己装进去 —— 两件都归引导层,信任根不能自举。
- ⛔ 不用 `webServer` / 前缀路由 / 页面级路由 —— 桌面端不存在这些。
- ⛔ 不替用户做「创建隔离实例」这类写平台库的动作 —— 平台不是实例,装不了插件。
- ⛔ 不动官方 DSH 主程序与缓存 —— 官方是 developer preview,改它会全量返工。
- ⛔ 不重造分发与更新机制 —— 平台侧共享包库与三只只读口已在机,重造等于两套指纹两套语义。
- ⛔ 本轮不改一行代码 —— ①段只出文档。
**说不换来什么**:把「实现一个平台」收敛成「实现一个包的契约」。六块模块里,只有四块能进包;多租户与覆盖网络只进数据面与界面,动作留给平台进程。聚焦之后,每条路径都能被门禁逐字断言(`build.mjs` 门禁 ①c–①h 已经在做这件事)。
---
## 6. 关键指标
- **北极星指标**:**用户拿到全套能力所需的安装次数**。目标=1(装官方 DSH + 一个包)。这个指标带动全部三条价值主张:次数降下来,切分 A 的入口问题、切分 B 的跨端问题才成立(来源:`1a` A2)。
- **本季 OMTM(只优化这一个)**:**六个模块里「两端都可用」的块数**。当前四块已实现(M5 / M3 / M2 / M6),两块只有数据面(M1 / M4)。这一季盯的就是把这个数从 4 往上推,推不动也要说清卡在哪(来源:`1a` A12 的缺口清单)。
---
## 7. 增长
- **自用形态,不是销售驱动。** 它服务的是本平台自己的租户与作者,没有获客渠道这一说(`1a` 的`【事实】`来源明确:这是自用形态)。
- **放量的方式**:不拉新用户,让同一个包覆盖更多实例。靠平台侧共享只读包库,一次投放到多台(来源:`1b §5` 投放维度)。
- **单位经济**:要盯的成本只有两项。一项是维护,一个包一个版本,改一块就得重发整包;另一项是投放,每次都要备份、都要留回滚素材。两项都靠把顺序固化成清单来压(来源:`1c` 画像三痛点 3)。
---
## 8. 能力
**需要哪些本事与资源**:
- 两端扩展点对齐的能力(已经把官方机制实测过一次,`1b §6`)。
- 插件数据面与迁移的能力(`dsh.data.yaml` 声明 + 平台侧执行器,已在机)。
- 逐字断言的机械门禁能力(`build.mjs` 门禁 ①c–①h,已在机)。
- 一个**平台侧插件宿主**。⚠️ 现状没有(来源:`1a` A12)。没有它,本包「平台那一半」永远落不了地。
**哪些自己做、哪些找伙伴**:
- 自己做:插件包本体、三套 SDK、客户端卡片、数据面声明。
- 不自己做(归别人):起实例(部署方案)、取身份与装包(引导层)、分发与更新机制(平台侧已有)。
- 找伙伴:不需要外部伙伴。本产品的约束是「不收外部付费接口」,全部用本平台与官方能力(来源:用户既定的收录标准)。
**要赢必须练出哪些能力**:
- **把契约写成机器能查的判据**。目前靠门禁逐字断言路径与注入点,这是唯一能防住「看着是绿的其实没生效」的办法。
- **把顺序写成可执行清单**。先建库再投放,投放必须留回滚素材。这类顺序靠人记就会漏(来源:`1c` 画像三痛点 3)。
---
## 9. 别人抄不走的地方
**竞品为什么不容易抄**:
- **聚合度**:把六块业务能力收进一个包,同时保住单块可回滚。这需要「表名分段 + 单入口按模块迁移」这套设计。同族包都选了「一块一个包」,回头改成聚合,数据面与投放链都要重做(来源:`1b §8` 矩阵)。
- **跨端一致**:这不是多一个功能,是一条硬约束(只用两端交集)。一旦允许用前缀路由或页面级路由,就再也回不到两端一致(来源:`1b §6`)。
**靠什么挡住**:
- **切换成本**:用户一旦把模型配置、插件注册、IM 房间、设备配对都装进这个包,换回「多包」形态要重新安置全部数据。
- **契约惯性**:包内门禁逐字断言路径与注入点,改契约要同时改门禁与全部调用方。
**新对手要进来的门槛**:
- 得先摸清「哪几件事插件做不到」(要写平台库的动作),否则会做出一个做不完的东西。
- 得先解决「桌面端没有 `webServer`」这条,否则做出来的东西桌面端用不了。
---
## 关键假设(必须成立才能赢)
按重要性排。每条给最小成本验证方式。
1. **平台侧插件宿主会建出来**(来源:`1a` A12 的缺口 ①)。
- 不成立的后果:本包「平台那一半」(多租户界面与请求之外的平台动作)永远落不了地。
- 最小验证:不用建宿主,先问一句「平台进程能不能加载一个包」——现状实测是**不能**(`1b §6` 的进程归属判定)。所以这一条靠**拍板**验,不靠跑代码。
2. **一个包一个库的分段设计,真能保住「单独回滚一块」**(来源:`1a` B5)。
- 不成立的后果:六块共库这件事变成纯负债,一次迁移失败牵动全部。
- 最小验证:拿一块(例如 M5)做一次「只回滚这一块表」的演练,看其余五块的表是否受影响。
3. **用户真的在意「聚合」而不是「能力条数」**(来源:`1c` 画像一的反直觉发现)。
- 不成立的后果:第一版优先做的事(收进入口)押错,用户要的其实是多接几块。
- 最小验证:把这句话直接问用户(`1a` 待复核清单第 1 条、第 11 条)。
4. **租户侧的跨端需求是真的**(来源:`1b §7` 与切分 B)。
- 不成立的后果:整套「只用两端交集」的约束是在为一个不存在的需求付代价(写死全路径、放弃前缀路由)。
- 最小验证:看桌面壳的实际使用率——若几乎没人用桌面壳,这条约束可以放宽。
5. **第三方插件作者是真实存在的角色**(来源:`1c` 数据缺口 3,`【推演】`)。
- 不成立的后果:三套 SDK 的稳定性不该占设计精力。
- 最小验证:数一数今天有几个包引了 `@dsh-local/ai1net/im-plugin-sdk` 这类导出。
---
## 附:输出检查
- [x] 九节都有内容,且互相自洽(愿景 → 切分 → 成本位置 → 价值主张 → 取舍 → 指标 → 增长 → 能力 → 护城河,逐节相扣)
- [x] 市场按要解决的问题切(要一次装齐 / 要跨端一致 / 要接能力),不按人口统计
- [x] 每个目标切分都写了价值主张四条(之前 / 怎么做 / 之后 / 替代)
- [x] 取舍一节写明了「不做什么」(七条)
- [x] 北极星指标(安装次数 = 1)与本季 OMTM(两端可用的块数)各一个
- [x] 挑出了「必须成立才能赢」的关键假设(5 条,各带最小成本验证方式)
- [x] 未引用 `1c` 里标 `【推演】` 的条目
@@ -0,0 +1,93 @@
# 1e · 使用场景(用户故事)—— AI1NET 基础插件
> 唯一句式:**作为【谁】,当【什么处境】,我要【办成什么】,这样【得到什么结果】**。四槽位缺一不算完成。
> 「我要办成什么」里**零功能名**(出现功能名即越界到②段)。「得到什么结果」写的是少掉的麻烦,不是愿景。
> 本份是②段功能清单的直接推导依据:②段每列一项功能,都要能追回下面某一条。
---
## 一、场景清单
### 1 · 换掉正在用的那个大模型
作为**正在跑一份要紧活的陈岚**,当**发现手头用的模型答得不合意、手上还有另一个模型的额度**,我要**把自己在用的那个换掉、并且让刚填进去的密钥不被任何人看到**,这样**我不用停下手里的活去等别人帮我改配置,也不必担心密钥在界面上留痕**。
(处境追溯:`1a` B6 的权限条与 `1b §5` 的「明文密钥只走一个入口」)
### 2 · 给这个实例装上我要用的本事
作为**刚接手一个实例的陈岚**,当**我发现这台机器上还没有我要的那项本事**,我要**把它装进来、并且马上知道它装上了没有**,这样**我不必反复开关页面去猜,也不必去问平台的人「装好了吗」**。
(处境追溯:`1a` A6;`1b §4` 场景 4)
### 3 · 让别人能跟我在这台机器上说话
作为**要拉一个同事一起看东西的陈岚**,当**我把东西准备好了、要叫上人一起看**,我要**开一个说话的地方、把该进来的人放进来**,这样**我不必凑合着用别处的聊天工具来回贴链接**。
(处境追溯:`1b §5` IM 能力维度)
### 4 · 把手机接到这台机器上
作为**要在外面处理事情的陈岚**,当**我在外面、手边只有手机,而东西都在这台机器上**,我要**让手机能连上这台机器**,这样**我不必等回到座位上才能动它**。
(处境追溯:`1a` 现状表 M6 行)
### 5 · 一次装完,不要再装第二个包
作为**刚买下一台新机器的吴敏**,当**我要把平台的全套本事都装到这台机器上**,我要**一次装完、以后更新也只更这一处**,这样**我不必记住哪台机器装了哪几个包、哪个包是哪个版本**。
(处境追溯:`1a` A1 / A2;`1b §8` 矩阵「一次装齐无人做好」)
### 6 · 桌面壳和浏览器里干一样的事
作为**白天用桌面壳、晚上用浏览器的陈岚**,当**同一件事我换了个端来做**,我要**两边都能做完、不用重新学一遍**,这样**我不必为了某一件事特地切回另一个端**。
(处境追溯:`1b §6` 两端交集;`1b §7` 跨端一致)
### 7 · 别人没经过我同意,就用我的身份做事
作为**负责这条交付线的吴敏**,当**我要确认某个能力确实只在自己那一份里生效**,我要**在拿不出凭据的时候它就直接拒绝、而不是拿本机的身份悄悄放行**,这样**我不必逐条去核「这件事到底是谁做的」**。
(处境追溯:`1a` B6;`1b §6` fail-closed)
### 8 · 一次改动不要牵动全部
作为**正要改其中一块的吴敏**,当**我只需要动其中一块、不想让别块跟着一起重来**,我要**能把这一块单独退回去**,这样**我不必为了一个小改动把整套东西回滚**。
(处境追溯:`1a` B5;`1b §5` 打包粒度维度)
### 9 · 升级坏了要能退
作为**刚上完一版就在盯着的吴敏**,当**新版本上线后不对劲**,我要**退回上一版、并且知道退回去的是哪一版**,这样**我不必临时从别处找旧包、也不必靠记忆判断现在是哪一版**。
(处境追溯:`1b §4` 场景 4;`1c` 画像三痛点 1)
### 10 · 东西装了但没生效
作为**做完一次投放的吴敏**,当**投放记录显示已经成功**,我要**能读出这台机器此刻真正在跑的是哪一版**,这样**我不必靠重启和猜来确认,也不会把「看着成功」当成「已经生效」**。
(处境追溯:`1c` 画像三的反直觉发现)
### 11 · 把自己的本事接进来
作为**想把自己的东西接进这套机制的周珩**,当**我决定接一次、不想重造轮子**,我要**照着说明接上去,并且接错的时候能立刻知道错在哪**,这样**我不必读源码去猜契约,也不会写完才发现方向不对**。
(处境追溯:`1a` A4;`1c` 画像二痛点 1 / 2)
### 12 · 接进来的东西不要因为我升级就坏
作为**已经接好一次的周珩**,当**这套东西发了新版本**,我要**我自己那部分不用改**,这样**我不必每次跟着升级重写一遍**。
(处境追溯:`1c` 画像二痛点 3;`1d §4` 切分 C)
### 13 · 装一次,就不要再问「装哪几样」
作为**准备开一个新实例的人**,当**我要拿到平台的全套本事、又不想逐项确认**,我要**一次装到位、并且能看清装上了哪几样**,这样**我不必对着清单一项一项核对**。
(处境追溯:`1a` A9;`1b §9` 可突破第 1 条)
---
## 二、完成判据核对
| 检查项 | 结果 |
|---|---|
| 四槽位齐全 | ✅ 13 条全含「作为 / 当 / 我要 / 这样」 |
| 「谁」是具体身份 | ✅ 用「正在跑一份要紧活的陈岚」「刚买下一台新机器的吴敏」「想把自己的东西接进来的周珩」这类具体身份,⛔ 无「用户」「某类人」 |
| 「处境」能追到 `1a` 某一行或原话 | ✅ 每条后面附了追溯;无一条只标`【判断】` |
| 「办成什么」零功能名 | ✅ 用用户的词写(「换掉正在用的那个大模型」「开一个说话的地方」「让手机能连上这台机器」),⛔ 未出现模块名、路由名、卡片名 |
| 「得到什么」写的是少掉的麻烦 | ✅ 全是「不必…」「不用…」式,⛔ 未写愿景 |
| 能原样念给用户听 | ✅ 每条都是完整口语句,不需要解释 |
## 三、与②段的约定
- ②段按本份梳理功能(一条场景可跨多个卡片),每列一项功能都要能追回上面某一条。
- 反向也成立:上面某条场景在②段推不出任何功能,就是空愿望 —— 要么补功能,要么删场景。
- 本份不写功能清单、不写界面结构、不写验收标准。