docs(wiki): 01-需求分析 改为「原生 vs 上游 vs 本 fork」对比式需求分析
把用户贴的 10 行 tab 表按供给来源拆成三层,逐行追问没有它时他会怎么办: - DSH 原生 = 右列容器 + 「文件」页 + documentpreview 文本兜底(证据 external-plugin-guide.md) - 上游 = 六个操作面(文件/变动/子代理/侧边对话/终端/浏览器) - 本 fork = 三个态势面(agents/apps/profile) 新增 7 条需求变化洞察(操作面→态势面、零切换棘轮、提问副作用归零、 看得见→敢放手、心智模型外化、价值随并行度放大、增量成本≈0), U1-U6 收敛为由分析推出的需求表;实现/根因只留附录索引。
This commit is contained in:
+120
-110
@@ -1,142 +1,152 @@
|
||||
# 01 · 需求分析
|
||||
# 01 · 需求分析:用户为什么会需要它
|
||||
|
||||
> **本篇只回答一个问题:使用者为什么会需要它。**
|
||||
> 每条需求都从「用户会怎么说」写起——他遇到什么处境、他想要什么结果、他怎样才算满意。
|
||||
> **不写我们是怎么实现的**:实现机制与故障根因在 [02-系统架构](02-系统架构) 与 [06-故障排查](06-故障排查),
|
||||
> 本篇末尾只留一份索引供开发/排障查阅。
|
||||
> 验收标准一律写成**用户能亲手点到、亲眼看到**的东西,不写测试用例名、不写提交号。
|
||||
> 本篇从**使用者**出发回答三个问题:
|
||||
> ① 他只用 DSH 原生右列时,一天是怎么过的?
|
||||
> ② 多了这些 tab 之后,他的**需求发生了什么变化**?
|
||||
> ③ 所以我们真正该满足的是什么?
|
||||
>
|
||||
> **不写实现**:机制与根因只在 [附录 A](#附录-a--实现与根因索引) 留索引,细节在 [02-系统架构](02-系统架构)、[06-故障排查](06-故障排查)。
|
||||
|
||||
## 一、谁在用
|
||||
## 一、先把"谁在用、他在哪儿干活"钉住
|
||||
|
||||
| 使用者 | 他在干什么 | 他对右侧栏的期待 |
|
||||
在 DSH 里,**右侧栏是用户一天里盯得最久的一块地方**。它不是"偶尔打开的设置页",而是"工作台 + 仪表盘"。
|
||||
|
||||
一个典型使用者(在 DSH 里做项目的人):
|
||||
|
||||
- 中间是对话主线——他和模型一起干活;
|
||||
- 右边是这块地方——看文件、看改动、看子代理、顺手追问、跑命令、看预览;
|
||||
- 他往往同时开着好几个会话、好几个项目。
|
||||
|
||||
这决定了本页所有需求的共同特征:**这些信息"看一眼就够,但要频繁看"。**
|
||||
频繁看的东西必须常驻在视野里——不能要求他"跳出去看一眼,再跳回来"。
|
||||
|
||||
## 二、同一块地方,三种供给:原生 / 上游 / 本 fork
|
||||
|
||||
| 供给来源 | 它给了什么 | 使用者的处境 |
|
||||
| --- | --- | --- |
|
||||
| 在 DSH Desktop 里做项目的开发者(主要) | 一边跟模型对话干活,一边开着文件、终端、预览 | 这是他一天里看得最多的那块地方:**别挡道、别自相矛盾、点开就有用** |
|
||||
| 同时放出去好几个子代理的「指挥者」 | 主会话里派活,子代理并行跑 | 不用翻聊天记录就知道**谁在跑、谁停了** |
|
||||
| 接手这套环境的同事 / 运维 | 装插件、升级、出事定位 | 装得上、看得出在跑、能退回去、文档照着做就行 |
|
||||
| **DSH 原生**(不装任何插件) | 一条空的右列容器、一个「文件」页、一个**文本/文档兜底预览**;DSH 自己的会话、任务、模型、设置也在这里 | 「地方是有了,东西得我自己张罗」 |
|
||||
| **上游工作台**(better-sidebar 系,本仓库的基座) | 把六个**操作面**搬进右列:文件、文件变动、子代理、侧边对话、终端、浏览器 | 「我不用离开这块地方,就能把活干了」 |
|
||||
| **本 fork(apes)** | 三个**态势面**:智能体、应用、画像 | 「我终于知道这摊活现在是什么状况了」 |
|
||||
|
||||
**一句话场景**:他打开 DSH,右列就是他的工作台;他希望在一个地方同时管住「文件、终端、预览」以及**这场会话的全局态势**。
|
||||
一句话概括这个分层的区别:
|
||||
|
||||
## 二、使用者的需求
|
||||
> **上游解决"怎么把活干了"(操作面),我们解决"我知不知道现在是什么状况"(态势面)。**
|
||||
> 前者省的是**动作**,后者省的是**心里的不确定**。
|
||||
|
||||
### U1 「我看不见谁在替我干活」
|
||||
这也是为什么三个 apes tab 的 `order` 是 60 / 65 / 70,排在原生 10–50 之后——
|
||||
那不是一个技术编号,而是一句设计判断:**态势信息属于"越过操作面、再看一眼全局"的那一层。**
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「我刚派了四个子代理,现在聊天记录刷得飞快——还剩几个在跑?哪个已经停了?」 |
|
||||
| **为什么难受** | 在聊天流里回溯是**唯一**的办法:往上翻,翻到就丢了上下文。原生会话树只回答"有哪些会话",不回答"这场会话里现在有谁、在干什么"。用户被迫在两个地方来回找同一条信息。 |
|
||||
| **他想要** | 点一下就有一张**这场会话的队伍表**:主代理在最上,它的直系子代理一人一行,谁在跑、谁停了,写在脸上。 |
|
||||
| **怎样算满意** | ① 不离开右列就能看到;② 人数与状态一眼可辨(运行中 / 已结束、一次性 / 可续);③ 没有子代理时**明确告诉他"没有"**,而不是留一片空白让他怀疑是不是坏了;④ 不用等刷新,开面板就是最新的。 |
|
||||
| **状态** | ✅ 已满足(`apes:agents`) |
|
||||
## 三、逐项对照:他为什么需要它,没有它时他会怎么办
|
||||
|
||||
### U2 「我不知道这活儿是在哪儿干的」
|
||||
| id / 名称 | 来源 | 他真正想要的是什么 | **只有原生时他会怎么做** | 有了之后 | 需求被改变成 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `editor` 文件 | 上游 | 看/改代码而不丢掉当前上下文 | ⌘Tab 跳到 VS Code 或别的编辑器;回来要重新找位置 | 右列里直接看、直接改 | 「看文件不该让我离开现场」 |
|
||||
| `git` 文件变动 | 上游 | 刚才到底改了哪些东西 | 切终端敲 `git status`/`git diff`,或再开一个 diff 工具 | 右列里一份变更清单 + 单文件 diff | 「改了什么必须当场看得见」(这是信任的前提) |
|
||||
| `subagent` 子代理 | 上游 | 进某个子代理,看它到底干了什么 | 翻会话树、翻聊天记录去认人 | 右列里直接进入该子代理 | 「子代理是可进入的,不是只能干等的」 |
|
||||
| `sidechat` 侧边对话 | 上游 | 追问一句,但不想污染主线 | 硬着头皮在主对话里问(把上下文搅浑),或另开一个窗口 | 旁路开一个小对话,两边互不干扰 | 「提问不该有副作用」——**性质变了** |
|
||||
| `terminal` 终端 | 上游 | 跑一条命令 | 切到系统终端;常常还得先 `cd` 到对的目录 | 右列里跑,工作目录天然就是对的 | 「命令的上下文应该跟着会话走」 |
|
||||
| `browser` 浏览器 / 预览 | 上游 | 看这个页面/HTML 出来是什么样 | 切浏览器标签页,或手动打开产物文件 | 右列内嵌,当场看 | 「产出物要能当场验收」 |
|
||||
| **`apes:agents` 智能体** | **本 fork** | 谁在替我干活、跑到哪了、哪个停了 | **基本没办法**——只能往上翻聊天记录,翻到一半又忘了上下文 | 主代理在最上,直系子代理一人一行,带运行/结束状态 | 「派了活之后,我要的是**扫一眼**,不是盯着守」(见 §四·洞察 4) |
|
||||
| **`apes:apps` 应用** | **本 fork** | 这摊活到底是在哪儿干的 | **基本没办法**——靠脑子记,或敲 `pwd` 确认 | 显示当前会话锚定的工作区 | 「界面应该告诉我我在哪,而不是要我自己记住」 |
|
||||
| **`apes:profile` 画像** | **本 fork** | 这个会话现在是什么状态 | 靠界面上的小细节猜(在跑?停了?哪一次?) | 标题 / 运行或空闲 / 工作区,写清楚 | 「离席回来,不用重建心智模型」 |
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「同时开着三个项目,会话标题长得都差不多——我现在这个是哪个目录下的?等下写文件会不会写错地方?」 |
|
||||
| **为什么难受** | 工作区是他**唯一**能确认"我在哪儿"的锚点,但它只存在于终端提示符里。切回一个会话时,他得先开个终端敲 `pwd` 才能安心。 |
|
||||
| **他想要** | 面板直接告诉他这场会话锚在哪个工作区;更好的是还告诉他这属于哪个「应用」。 |
|
||||
| **怎样算满意** | ① 打开就能看到工作区路径(不用他自己去敲命令);② 拿不到应用层信息时**如实写"宿主现在没有应用信息"**,而不是留空让他猜哪里出了问题。 |
|
||||
| **状态** | ◑ 部分满足:工作区 ✅(`apes:apps`)/应用层信息受宿主限制(见 §四) |
|
||||
(`diff` 是内部类型、非用户可见,不占需求;此处略。)
|
||||
|
||||
### U3 「这个会话现在是什么状态、值不值得等」
|
||||
## 四、深度分析:需求到底发生了什么样的变化
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「它还在跑吗?还是刚才就停了?我刚回来,这个会话是哪一次来着?」 |
|
||||
| **为什么难受** | 会话的"身份"和"当前状态"散落在界面细节里,要靠猜;离开一会儿回来,就要重新建立"我在看什么"的心智模型。 |
|
||||
| **他想要** | 一张**会话画像**:这次会话是什么、现在在跑还是空闲、工作区在哪儿。 |
|
||||
| **怎样算满意** | ① 运行 / 空闲有明确文字,不用看动画猜;② 标题或工作区缺失时给出替代信息或明确提示。 |
|
||||
| **状态** | ✅ 已满足(`apes:profile`:标题 / 运行态 / cwd) |
|
||||
### 洞察 1 · 从「操作面」到「态势面」:省的东西不是一类
|
||||
|
||||
### U4 「我点开一个 HTML,结果只有一行 forbidden」
|
||||
六个上游 tab 省的是**动作**——把原本要切窗口/切应用做的事,搬到他眼前。
|
||||
三个 apes tab 省的是**不确定性**——他不用再"猜""记""翻"。这两类需求的满足方式不同:
|
||||
动作可以被"更快的操作"替代,不确定性**只能被"看得见"消除**。
|
||||
所以哪怕将来操作类插件做得再好,态势类需求仍然空着——这就是本 fork 存在的位置。
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「模型给我生成了一份报表 / 图表 / 原型页面,我点开——就一行 `forbidden`。文件是坏了吗?」 |
|
||||
| **为什么难受** | HTML 是最直观的**交付物**,也是他最想直接验收的东西。看到的却是一行技术错误:他既不知道文件是好是坏,也不知道该找谁。信心成本很高——一旦怀疑"预览不可信",他下次就直接绕开功能,回到最原始的"下载下来用浏览器打开"。 |
|
||||
| **他想要** | 点开就能看到内容。**而且不希望为了让他看见,就把安全边界拆掉。** |
|
||||
| **怎样算满意** | ① 自包含 HTML(内联样式/脚本)完整显示;② 多文件 HTML 至少正文可读,需要外链资源时由**他本人**点「临时解锁」这个显式动作来放宽;③ 真取不到文档时,显示真实原因,不是白屏。 |
|
||||
| **状态** | ✅ 已满足(默认沙箱态可读;多文件需显式解锁,见 [03-功能说明](03-功能说明) §3.1) |
|
||||
### 洞察 2 · 「零切换」会变成默认预期(棘轮效应)
|
||||
|
||||
### U5 「我的界面自己乱套了」
|
||||
一旦右列里能看文件、能跑命令、能看预览,用户对"跳出去一下"的容忍度会**永久下降**。
|
||||
他会开始说「为什么这个还要我切窗口?」——而这句话在他用原生时是说不出口的(因为原生本来就没有)。
|
||||
**这类需求只会前进,不会后退。** 这也是为什么这块地方值得投入:它一旦被填好,就变成基础设施。
|
||||
|
||||
**a. 右边有两套侧边栏,我不知道该点哪个**
|
||||
### 洞察 3 · 消除副作用之后,他会开始"问"
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「窗口右边出现了两个侧边栏、两个开合按钮——哪个是真的?」 |
|
||||
| **为什么难受** | 两个入口、两套内容,用户无法判断该用哪个;他会同时试两个,再怀疑是不是装重了。**不可信的工具会先被弃用**,然后才被排障。 |
|
||||
| **他想要** | 右列只有一套——DSH 自己那套;插件的东西**住在里面**,而不是另起一套。 |
|
||||
| **怎样算满意** | 右列只有一个展开/收起入口;插件每个面板都能从原生入口进入;不会出现"关掉一个还剩一个"。 |
|
||||
| **状态** | ✅ 已满足 |
|
||||
`sidechat` 的价值不在"多一个对话框",而在**把提问的代价从"可能污染主线"降到"零"**。
|
||||
需求的性质变了:以前他的问题是「要不要问?」(一个决策),现在变成「顺手问一下」(一个动作)。
|
||||
**当一件事的代价趋近于零,用户的行为频率会跳一个数量级**——这是需求分析里最值得警惕也最值得利用的一条规律。
|
||||
|
||||
**b. 弹窗被插件面板切掉一角**
|
||||
### 洞察 4 · 看得见 → 敢放手(`apes:agents` 的核心价值)
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「我打开插件市场,弹窗左下角被切了一块,按钮点不到。」 |
|
||||
| **为什么难受** | 他遇到的不是"功能缺失",而是**功能互相打架**:明明能用的东西被自己的插件挡住。这类问题最伤使用意愿,因为用户会归咎于"这个插件不可靠"。 |
|
||||
| **他想要** | 弹窗是更上层的东西,应该完整盖住插件面板;同时插件面板仍要盖在对话正文之上。 |
|
||||
| **怎样算满意** | 弹窗完整可见、按钮可点;面板不回退到被对话正文压住。 |
|
||||
| **状态** | ✅ 已满足 |
|
||||
这是本 fork 最值钱的一条:
|
||||
|
||||
### U6 「我不敢升级——也不知道该装哪一版」
|
||||
- 原生/上游给的是**导航型**信息——「有哪些子代理会话可以点进去」;
|
||||
- `apes:agents` 给的是**态势型**信息——「这场会话的队伍:主代理 + 直系子代理,谁在跑、谁停了」。
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **他会怎么说** | 「升了一版,插件就像没装一样,没报错也没日志。我这台该装哪版?出事怎么退回去?」 |
|
||||
| **为什么难受** | 宿主对版本不匹配是**静默禁用**——没有错误提示,用户只会得出"这东西坏了/不可信"的结论,而真正的原因是版本配错。加上换机器、多环境,选线成本全压在用户的记忆里。 |
|
||||
| **他想要** | ① 一份"哪个宿主配哪个版本"的对照,照着选就能装上;② 每步升级都留可回滚的锚点;③ 万一装错,文档能告诉他"现象就是像没装"以及怎么换回来。 |
|
||||
| **怎样算满意** | ① 按 [04-部署指南](04-部署指南) 的对照表选线即装得上;② 升级前后有分支/tag,一条命令回退;③ 能在 [06-故障排查](06-故障排查) 里按症状自查。 |
|
||||
| **状态** | ✅ 已满足(两条版本线 + 锚点;新宿主线待实机验证,见 [05-运维手册](05-运维手册)) |
|
||||
用户真正的痛点不是"我进不去子代理",而是**"我不敢派太多活"**:
|
||||
因为看不见,他只能用"盯着"来对冲风险,而盯着就失去了并行的意义。
|
||||
|
||||
## 三、我们不做的事(先说清,省得期待错位)
|
||||
> **看得见 → 敢放手 → 真的并行 → 才配得上"多智能体"。**
|
||||
> 需求从「我要能看见」升级为「我要能放心」。
|
||||
|
||||
| 不做 | 对使用者意味着 |
|
||||
| --- | --- |
|
||||
| 不重造「文件 / 终端 / 浏览器」 | 这些上游与宿主已经有了,再造一遍只会让你的界面更乱 |
|
||||
| 不做团队 / 房间 / 多智能体协作面板 | 那是宿主另一类能力的职责,不该塞进右列 |
|
||||
| 不为「看得见」放宽沙箱 | 想加载沙箱外资源,必须由**你本人**点一次显式解锁;插件不会替你默默降级 |
|
||||
| 不承诺"装上看不见变化"就是坏的 | 宿主对版本不匹配是静默禁用,先按 [06-故障排查](06-故障排查) 自查宿主版本 |
|
||||
### 洞察 5 · 心智模型从脑子里搬到界面上(`apps` / `profile`)
|
||||
|
||||
## 四、已知的「暂时满足不了」(如实交代)
|
||||
多项目、多会话的人在切换时要重建一次"我这是在哪儿"——标题差不多的会话最容易看错,
|
||||
而看错的代价是写错文件。`apes:apps` / `apes:profile` 做的是**把这份"我记得"外化成"界面写着"**。
|
||||
需求的性质:从「我要记性好」变成「界面不该让我记」。(注意:目前只做到工作区粒度,
|
||||
**应用层的需求还没有被满足**——见 §七。)
|
||||
|
||||
| 使用者想要的 | 现状 | 为什么 | 何时会好 |
|
||||
### 洞察 6 · 这三个 tab 的价值随"并行度"放大
|
||||
|
||||
- 单会话、单项目的用户:`apps`/`profile` 几乎用不上,`agents` 也只有一个主代理;
|
||||
- 一旦同时开几个会话、派几个子代理、换几个项目:这三个 tab 的边际价值**陡增**。
|
||||
|
||||
所以这套东西**不是人人需要,但接到的人离不开**——这正是"信息层插件"该有的形状:
|
||||
它不改变你能不能干活,它改变你**敢不敢多干**。
|
||||
|
||||
### 洞察 7 · 成本几乎为零,这是它值得装的理由
|
||||
|
||||
这三个 tab **不新增数据源、不新增进程、不引入新的失败面**:它们只是把宿主已经投影出来的信息
|
||||
换一个"用户视角"呈现(数据来源逐条列在 [03-功能说明](03-功能说明))。
|
||||
对使用者意味着:没有额外负担、没有额外风险——**只是原来就存在的东西,忽然变得看得见了。**
|
||||
"低风险地换到确定性"是这类插件最好的推销词,也是它该守住的边界。
|
||||
|
||||
## 五、由以上分析推出的需求(U1–U6)
|
||||
|
||||
| # | 需求(用户口吻) | 怎么算他满意了 | 现状 |
|
||||
| --- | --- | --- | --- |
|
||||
| 应用级信息(这场会话属于哪个「应用」、有哪些入口) | `apes:apps` 只显示工作区 cwd | 宿主当前没有向插件提供应用清单的通道 | 宿主提供 feed 后即可接上 |
|
||||
| 一次摊开完整子代理树(含子代理的子代理) | 只显示**直系**子代理 | 宿主投影只给一层 catalog | 同上 |
|
||||
| 沙箱态下多文件 HTML 的相对资源 | 需点「临时解锁」 | 不透明源沙箱里子请求拿不到宿主信任头——这是安全边界的必然结果 | 刻意保留,不计划改变 |
|
||||
| U1 | 「我要看得见谁在替我干活」 | 右列点一下就有队伍表;人数/状态一眼可辨;没有子代理时明确说"没有",不是空白 | ✅ `apes:agents` |
|
||||
| U2 | 「我要知道我是在哪儿干的活」 | 打开就看到工作区路径,不用敲 `pwd`;拿不到应用信息时如实说明 | ◑ 工作区 ✅ / 应用层等宿主 |
|
||||
| U3 | 「我要知道这个会话现在什么状态」 | 有明确的运行/空闲、标题、工作区 | ✅ `apes:profile` |
|
||||
| U4 | 「我点开 HTML 就该看得见」 | 自包含 HTML 完整显示,而不是一行 `forbidden`;**但不许为此拆掉沙箱** | ✅(多文件需我本人点「临时解锁」) |
|
||||
| U5 | 「我的界面不许自己乱套」 | 右列只有一套侧边栏、一个开合入口;弹窗完整盖在面板之上、按钮点得到 | ✅ |
|
||||
| U6 | 「我敢升级,也退得回去」 | 有"宿主版本 ↔ 插件版本"对照表;每步升级都有分支/tag 可回滚 | ✅ 两条版本线;新宿主线待实机验证 |
|
||||
|
||||
## 五、验收总表(你可以自己动手验)
|
||||
## 六、我们不做的事(省得期待错位)
|
||||
|
||||
| 你做什么 | 你应该看到 |
|
||||
| --- | --- |
|
||||
| 展开右列 | 只有**一套**侧边栏、**一个**开合入口 |
|
||||
| 点「智能体」 | 主代理 + 直系子代理,带运行态;没有子代理时明确提示"没有" |
|
||||
| 点「应用」 | 当前工作区路径;宿主无应用 feed 时写明原因 |
|
||||
| 点「画像」 | 会话标题 / 运行或空闲 / 工作区 |
|
||||
| 打开一个自包含 HTML | 内容完整显示在面板里,不是 `forbidden` |
|
||||
| 打开一个多文件 HTML | 正文可读;需要外链资源时由你点「临时解锁」 |
|
||||
| 打开插件市场 | 弹窗完整盖在面板之上,按钮可点 |
|
||||
| 打开某个 HTML 后 ⌘Q 重启 DSH | 面板仍在、开合入口仍只有一个 |
|
||||
- **不重造文件/终端/浏览器。** 上游与较新宿主已经提供;再画一套只会让右列变乱。
|
||||
- **不为"看得见"放宽安全边界。** 需要放宽必须由用户**本人显式点**「临时解锁」。
|
||||
- **不做团队/房间/多智能体协作编排。** 那是宿主的另一类职责。
|
||||
- **不承诺"装上立刻见效"。** 单会话用户可能几乎感觉不到差异(见洞察 6)。
|
||||
|
||||
## 六、优先级与当前状态
|
||||
## 七、已知的「暂时满足不了」(诚实交代)
|
||||
|
||||
| 需求 | 优先级 | 状态 |
|
||||
| 他想要的 | 现状 | 为什么(一句话) | 何时会有 |
|
||||
| --- | --- | --- | --- |
|
||||
| 知道这摊活属于哪个**应用**、有哪些入口 | `apes:apps` 只显示工作区 | 宿主目前没有向插件提供应用清单的通道 | 宿主提供 feed 后即可接上 |
|
||||
| 一次摊开**完整**子代理树(子代理的子代理) | 只显示**直系** | 宿主投影只给一层 | 同上 |
|
||||
| 沙箱状态下多文件 HTML 的相对资源 | 需点「临时解锁」 | 不透明源沙箱下子请求拿不到宿主信任头(安全边界的必然结果) | 不打算改——这是刻意保留的边界 |
|
||||
|
||||
> 这三条说明同一件事:**需求跑在宿主能力前面**。写出来不是免责,是让读的人知道
|
||||
> "不能用"和"还没做"是两回事。
|
||||
|
||||
## 附录 A · 实现与根因索引
|
||||
|
||||
开发与排障看这里;其余读者可跳过。
|
||||
|
||||
| 需求 | 机制(去哪看) | 关键证据 |
|
||||
| --- | --- | --- |
|
||||
| U1 看得见队伍(谁在替我干活) | P0 | ✅ `apes:agents` |
|
||||
| U4 HTML 看得见、且不降级安全 | P0 | ✅ 默认沙箱可读;多文件需显式解锁 |
|
||||
| U5 界面别乱(单一侧边栏 + 层叠正确) | P0 | ✅ |
|
||||
| U6 敢升级、能回滚 | P1 | ✅ 两条版本线 + 锚点;新宿主线待实机验证 |
|
||||
| U2 知道在哪儿干活 | P1 | ◑ 工作区 ✅/应用层等宿主 |
|
||||
| U3 会话画像 | P2 | ✅ `apes:profile` |
|
||||
| U5-a 右列只有一套侧边栏 | 插件把每个 tab 注册成原生 tab 类型(`kind = descriptor.id`)渲染进 DSH 自己的右列;自绘面板已移除 | [02-系统架构](02-系统架构)、[05-运维手册](05-运维手册) |
|
||||
| U5-b 弹窗不被面板切 | 宿主容器上的层叠上下文(`isolation`)导致;宿主挂载点改挂 `#root` 而不再挂 `document.body` | [06-故障排查](06-故障排查) |
|
||||
| U4 HTML 预览 | 主框架 `fetch` → `srcDoc`,**`sandbox` 属性未动**;失败回退路由 URL | [06-故障排查](06-故障排查) |
|
||||
| 原生右列到底自带了什么 | 原生提供右列容器 + 「文件」页 + `documentpreview` 文本兜底;插件的 `editor` 类型以 `extension` 优先级压过该兜底并接管 `files` 页,卸载即复位 | `docs/external-plugin-guide.md` §「内置类型接管」 |
|
||||
| U6 版本线 | 宿主版本不匹配时宿主**静默禁用**整行(不报错、无日志);`^` 跨 minor 判 false | [04-部署指南](04-部署指南)、[06-故障排查](06-故障排查) |
|
||||
|
||||
## 附录 A · 根因档案(实现视角,开发与排障看,其他读者可跳过)
|
||||
|
||||
| 需求 | 机制 / 证据 | 详细页 |
|
||||
| --- | --- | --- |
|
||||
| U1 / U2 / U3 信息层三 tab | 按 DSH 标准 `TabDescriptor` 注册(`order` 60/65/70、`single`);数据来自 `ctx.sessions.list` 的 `byId` 与宿主会话投影;随基线同步进两条版本线 | [02](02-系统架构) · [03](03-功能说明) |
|
||||
| U4 HTML 预览 | 桌面壳对**所有**路由做前置围栏,只信任带 Electron 注入头的请求;沙箱 iframe 源为 `null` 因而发不出合规请求。解法:主框架 `fetch` 取文档 → 注入 `<base href>` → `srcDoc` 交付,**沙箱令牌一字未改** | [06](06-故障排查) · [03](03-功能说明) §3.1 |
|
||||
| U5-a 两套侧边栏 | fork 基线 v0.18.0 自绘右列与开关(`toggleCluster`),而 DSH 自带原生右列;升级到上游 v0.19.1(原生注册路径)后仅剩一套 | [02](02-系统架构) |
|
||||
| U5-b 弹窗被切 | 桌面壳给 `#root` 加 `isolation: isolate` 形成层叠上下文,宿主 overlay(`z-index: 1000`)被封在其中;插件面板宿主当时挂在 `document.body`(上下文之外)且带 `z-index: 25`。解法:把面板宿主挂进 `#root`,无标记时回退 `document.body` | [02](02-系统架构) · [06](06-故障排查) |
|
||||
| U6 静默禁用 | 宿主启动预检 `semver.satisfies(host, peerRange, { includePrerelease: true })`,caret 跨 minor 为 false → 整行跳过,无日志。对策:两条独立版本线 + 分支/tag 锚点 | [05](05-运维手册) · [04](04-部署指南) |
|
||||
<!-- 本页只讲"为什么需要"。实现细节、提交号、测试名一律留在 02–07 与附录索引里。 -->
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ cordis entry id 冲突,第二个会被丢弃):
|
||||
|
||||
| 页面 | 内容 |
|
||||
| --- | --- |
|
||||
| [01-需求分析](01-需求分析) | **使用者视角**:谁在用、他为什么会需要(U1–U6,附验收动作)、不做什么、已知限制;实现根因只留索引 |
|
||||
| [01-需求分析](01-需求分析) | **用户为什么会需要**:原生 / 上游 / 本 fork 三种供给对比、逐 tab「只有原生时他怎么办」、7 条需求变化洞察、U1–U6、已知限制 |
|
||||
| [02-系统架构](02-系统架构) | host/client 拆分、三层接口面、面板宿主层级契约、关键不变量 |
|
||||
| [03-功能说明](03-功能说明) | 全部标签页与预览器、信息层数据来源、i18n、主题令牌、安全边界 |
|
||||
| [04-部署指南](04-部署指南) | 环境矩阵、选线、profile 接线、构建、验收清单、卸载 |
|
||||
|
||||
Reference in New Issue
Block a user