124 lines
15 KiB
Markdown
124 lines
15 KiB
Markdown
# dsh-worktable 项目规则
|
||
|
||
> 工作台容器插件:侧边栏里收纳 agent 级项目的「应用抽屉」。纯增量,不替换官方插件。
|
||
|
||
## 协作方式(用户定案,最高优先级)
|
||
|
||
- **设计先给最小版**:任何 UI/文案/方案先交「最少元素」版本给用户拍板,确认后再增量;
|
||
默认克制——没有存在理由的元素不放;不一次搭「完整版」再返工。
|
||
- **长任务拆 checkpoint**:每个可验收阶段完成后停下汇报,等用户确认再进下一段;
|
||
不一口气跑完长任务。
|
||
- **对外动作永远先审**:发布、评论、给观众的内容、任何公开操作,一律先给用户过目,
|
||
用户不点头不执行。
|
||
- **改完必读回**:每次编辑后读回改动处的完整行/段落,确认无残留、无断尾
|
||
(包含命令与 URL)。
|
||
- **验收用最终产物,不用中间信号**:任何交付物(tgz、命令、文档、UI)的验收动作必须是
|
||
「解包 / 复制 / 实跑用户路径」;「构建成功」「bundle 里有字符串」「退出码 0」不算验收。
|
||
- **发布前自跑最终产物清单**:干净目录安装、最终包逐文件核对、双资产哈希、关键行逐字
|
||
grep —— 先自查再报告,不等外部复审来抓。
|
||
- **发布包验收=结构检查 + 真实安装**:标准 package/ 前缀、白名单精确 7 文件(无 src/、.map),
|
||
再独立目录 npm install + import() 断言;仅核对文件存在不能证明包可安装。
|
||
- **声明可证伪**:只写已验证范围;安装/导入不是端到端验收,版本比较正常不等于通知覆盖所有用户。
|
||
- **同 tag 资产不可覆盖(用户已拍板)**:坏包处理 = 发新版本号 + 旧 Release 正文标注问题,
|
||
默认不替换旧资产;仅经用户明确批准的紧急补救例外,且须:不改名(保持原 URL 名)、
|
||
用已验证包、不删不盖现有资产、上传后从完整 URL 下载核对、旧 Release 注明补救经过。
|
||
|
||
## 边界
|
||
|
||
- 插件包根目录 = `01_content/`;本仓库其余目录是项目文档与本地工具。
|
||
- **不替换、不禁用任何官方插件**(ui-sidebar / ui-workspace / ui-layout)。
|
||
- 项目/布局/绑定存 localStorage,媒体存 IndexedDB;文件窗、mkdir 与产物握手会读写用户配置的项目目录,权限边界见 `01_content/README.md`。
|
||
- dsh-travelatlas 是入驻项目而非本仓库的一部分;协议见 `02_process/PRD.md` §5.3/5.4。
|
||
- **平台边界**:Windows 网页端已测范围见 `01_content/README.md`,不宣称全功能验收;桌面已测版本与候选边界同包内 README;macOS 为实验性支持(核心文件路径代码已做跨平台适配,
|
||
尚未真机端到端验证)。路径拼接必须走 `pathutil.ts` helper 或 Node `path` API,不手写分隔符。
|
||
|
||
## 当前 0.5.0 安全与兼容范围
|
||
|
||
- 私有 HTTP/终端握手统一调用 `requestAuth.ts`:新宿主要求 owner,0.2.0 仅放行同一 operator 对象;未知/不可用服务关闭访问,不用 requestRejection-only 回退。health 与随机只读预览地址是明确例外。
|
||
- `SandboxedFrame` 禁止 `allow-same-origin`;本地目录先鉴权创建临时只读挂载,Desktop 资源走 Host HTTP 地址。不得为恢复页面存储/自动取字而取消隔离。影响、保活与过期语义必须见包内 README。
|
||
- 预览读取必须绑定同一文件句柄、限量并复核文件身份/路径及撤销状态;保留目录替换/检查后增长等回归。该机制不等于恶意本地进程的 OS 文件沙箱,文档不得作绝对防护承诺。
|
||
- 当前版本只声明 DSH 0.2.0-rc.2 / 0.2.1-rc.3;网页隔离实测与 Desktop 传输单测不能冒充真实 Desktop 全功能验收。下文旧版本兼容条目是历史依据。
|
||
- `npm run test:security` = 22 项源码/夹具回归;流水线源码回归合计 122 项。安装产物另跑 `node 04_test/split-margin.test.mjs [client.js 路径]` 的 5 项真实 Chromium 回归(Edge/Chrome 或 `DSH_TEST_CHROMIUM`),改 margin/换根观察器必须保留旧产物变红的回归证据。
|
||
|
||
## 构建与验证
|
||
|
||
```powershell
|
||
cd 01_content
|
||
npm install
|
||
npm run build # lib/index.js + lib/client.js
|
||
node --check lib/index.js
|
||
```
|
||
|
||
- 客户端 bundle 必须保持 `window.__ModuleLoader__.load` 握手与 external react/@deepseek-ai/*。
|
||
- 变更视图状态结构时同步更新 PRD 的持久化说明。
|
||
- **构建必须 `cd 01_content` 后执行**:误在仓库根跑会把 lib 写到仓库根 `lib/`,宿主仍加载
|
||
`01_content/lib` 旧 bundle,出现「改完不生效」假象(已有教训,见工作日志)。
|
||
- **发布打包唯一入口 = `npm run pack`(01_content/release-prep.mjs)**:身份断言(package/manifest/cordis.patch.yml 严格结构)→
|
||
版本一致性 → **会话/输入/传输/挂载/安全回归**(当前 122 项,评估源码契约及夹具)→ 构建(cwd 固定 01_content)→ node --check → npm pack → 结构清单断言(package/ 前缀 + 精确 7 文件,
|
||
无 src/、无 .map)→ 独立临时目录 npm install + import() 断言(apply 函数/inject 含 webServer+sessions/name/
|
||
HEALTH_PATH/包内双 bundle 版本)→ **客户端工厂求值门禁**(ModuleLoader 恰好注册一次 + ID 校验 + 精确外部依赖
|
||
白名单 react/react/jsx-runtime + apply/inject 断言)→ **分栏锚点 DOM 回归**(14 场景,评估安装产物 lib/client.js;
|
||
测试接受包路径参数)→ **侧栏弹窗回归**(安装产物,展开/收起共用层)→ **真实 Chromium 分栏 margin 回归**(5 场景,评估安装产物)→ **服务端数据目录回归**(3 组场景,评估安装产物 lib/index.js)→ dist/v版本号/ 双资产(终态恰好 2 文件 + 双 SHA 同源)。
|
||
脚本零 git/gh 动作,发布上传由 gh 手动完成。
|
||
**发布禁止裸 npm pack 或手工 tar 生成发布包**;脚本从仓库任意目录调用均安全(以自身位置解析)。
|
||
- 弹窗必须由展开/收起两种侧栏共用一份 JSX 层;保留路径选择失效/卸载守卫,禁止再复制弹窗。`npm run test:sidebar` 评估实际构建组件,旧缺失/重复渲染应变红。
|
||
- **配套检查入口**:`npm run test:gate` = 工厂门禁 10 个失败/正向用例;
|
||
`npm run test:widget` = 项目/会话归属、共目录、延迟结果与补挂重试 26 项回归(执行实际函数,不等于模型生成端到端验收);
|
||
`node 04_test/anchor-dom.test.mjs [lib/client.js 路径]` = 分栏锚点 14 场景(缺省用工作目录构建产物);
|
||
`node 04_test/server-home.test.mjs [lib/index.js 路径]` = 数据目录解析 3 组场景(子进程隔离夹具;
|
||
**突变体验证法**:把 loadPkg 兜底的 baseDshHome() 故意改回 resolveDshHomeSafe() 恢复循环,测试必须红)。
|
||
`npm run verify:remote -- --expect-sha <release-prep 输出的 SHA> [tag]` = 发布后只读核对
|
||
(远端固定名+版本化双资产文件名/结构/版本/双 SHA 同源且等于本地验收 SHA/安装/导入;
|
||
远端只读,本地仅临时目录)。上传后必须跑 verify:remote 并用 --expect-sha 比对,
|
||
防「双资产同错」;tag 模式断言 tag==='v'+包内版本。
|
||
|
||
## 领域约定(会话中必须遵守)
|
||
|
||
| 实现参考 | 对应材料 |
|
||
| --- | --- |
|
||
| 接口鉴权、预览能力、隔离限制与验收边界 | `docs/compatibility-and-security.md` |
|
||
| 控制室 UI、预设/模型、提醒、产物握手、更新状态 | `02_process/PRD.md` §14(修改对应组件时对照源码,不以历史 API 示例替代新旧桥接) |
|
||
|
||
- **Desktop 兼容边界**:0.4.0 保留客户端 platform=web(Desktop 0.2.0-rc.2 也按此契约加载)。终端 WebSocket 经 `hostTransport.ts` 使用宿主 `__DSH_TRANSPORT__.streamBaseUrl`,不能由 dsh-app://app 拼 ws://app;更新提示须指向 desktop profile 与桌面端自带 CLI,不能修改 web profile。页面点测与源码回归不能替代完整桌面端业务验收,不宣称桌面全功能兼容。
|
||
- **0.3.4 网页端兼容**:声明已测版本 0.1.1-rc.2 / 0.1.2-rc.1 / 0.2.0-rc.2,不外推 Desktop 或未测宿主。当前会话走 `currentSessionOf`(旧 current / 新 mainView),导航走 `openHostSession`(新 uiWorkspace / 旧 sessions.open),标注走 `appendHostInput`。Cordis 可选服务用 `ctx.get` 探测;返回 undefined 后不得再访问未 inject 的同名属性。旧 current 契约的引用坐标是显示文本位置,新 mainView 契约按单字符 chip 投影;不得因旧版也有 input.for 就误用新版坐标。`npm run test:input` 为 15 项定向回归。
|
||
- **0.2 会话状态/发送**:可选订阅 `uiSession.sessionStatus`,只读归一化列表与 subagentCatalog;completionUnread 不是任务成功证明,打开主会话会清除。已观察到的 running→false 供原产物握手使用,下一轮 running 清除;停止不等于成功。新会话发送通过 `sessions.using` 临时持有,等待 ready 后发送并由宿主释放;业务拒绝/超时不得再换通道重发。`npm run test:session` 为 20 项回归;0.2.0-rc.2 已实测短文本发送/回复,真实待决/子代理仍未验收。
|
||
- **0.2 新建/预览/选择接口**:`createHostSession` 必须区分显式未分组(第四参数 `none`)与隐式默认(`auto`)。自定义窗口显式未分组仅传 cwd(无目录则空选项),禁止注册/复用工作区或 initializeDefault;新版控制室空未分组会话输入区禁用,必须提示并阻止创建,由用户选组/加入可用现有会话,不偷偷改组、不发激活消息。现有分组未选 ID 同样拒绝;显式现有/新建组才传 workspaceId。分组列表晚返回不得覆盖用户已选分组。隐式默认保留此前工作区兜底,旧宿主保留原分支,不移动既有会话。预览读临时持有的 eventSource,模型目录在持有期间使用,结束即释放;预设接 remote.agentPresets。`npm run test:details` 为 30 项回归,含两处真实调用接线与延迟默认分组;不能替代真实输入区/模型会话验收。
|
||
|
||
- **窗口编号**:用户说「窗口1/2/3…」指布局里按「左栏 → 顶行 → 主行」顺序的第 N 个内容窗。
|
||
例:田字格预设(g4)窗口1/2 = 顶行左右、窗口3/4 = 底行左右;l13 窗口1 = 顶部大窗,
|
||
窗口2/3/4 = 底部三小窗(从左到右)。需要定位时按此映射,不要凭猜测。
|
||
- **预设追加规则**:新布局预设只允许追加到 `PRESET_DEFS` 末尾(选择器里的「+自定义」磁贴
|
||
永远是最后一个);字段 leftCount/topCount/contentCount/chatFull/topHeightDefault/topHeightRatio,
|
||
聊天窗恒在右侧;缩略图在 presetThumb() 加分支。
|
||
- **分栏锚点与还原**:历史宿主三种根结构、零高包装取可见头部的规则见 PRD §12.4;同根重锚仅在锚点更换时保存原值,避免关闭时泄漏 margin/宽度。写入 margin 后须从 CSSOM 读回基线;换 viewArea 同步重绑让位观察器。改动必须跑锚点与真实 Chromium 回归,保留旧产物变红证据。
|
||
- **数据目录解析无循环**:resolveDshHomeSafe 优先官方 home-paths,再 baseDshHome;loadPkg 兜底只能调 baseDshHome,不得反调 resolveDshHomeSafe。DSH_HOME 空白视未设;实际路径保留两端空格,支持 ~、~/、~\\ 与相对 cwd,默认 ~/.dsh。不得新增 dsh-home-paths 生产依赖(旧宿主 peer cordis 不兼容)。修改须跑 server-home 三组与循环突变体检查。
|
||
- **新会话策略**:创建后应用默认预设与有效模型;桥接保持原选择策略,持有结束即释放。失败不重复发送;插件导航须 markPluginSessionOpen,未绑定项目成功任务会 autoBind。
|
||
- **项目文件夹**:保存要求绝对路径,mkdir 非 2xx 必须中止;自定义任务带项目 cwd,产出落该目录。
|
||
- **窗口任务**:buildWindowTaskText 统一携带窗口身份/项目目录/通用知识;不重复侦察插件源码。
|
||
- **产物握手 v2**:目录不是项目身份。`widgetMount.ts` 校验 projectId/paneId/bindingId,禁止扫旧根清单或回退窗口1。提示词与完成读取限本会话;补挂重读并复验归属,成功后才清待办。手工关闭/替换撤销关联,追改可复用,完成不证明成功。协议见 PRD §14。
|
||
- **原生皮肤**:template/dshell.css + dshell.html 为单一来源,经 /api/worktable/template 下发;新增样式只加模板。
|
||
- **提示词零泄漏(硬约束)**:所有对外生成的提示词(buildWindowTaskText 窗口任务提示词、
|
||
buildCustomLayoutPrompt 剪贴板布局提示词)禁止写入用户的个人工作区分组名(如 Projects /
|
||
DeepseekHarness)、其他用户的项目名与私人路径。剪贴板提示词会发给别人的 DSH,必须只含
|
||
插件通用知识;窗口任务提示词只发用户自己的会话,允许携带该项目自己的文件夹路径。
|
||
分组下拉只是会话创建工作区的选择,绝不进入任何提示词文本。
|
||
- **提醒红线**:need > done > busy,聚合父/子会话。ack 只存 opaque key/kind,不存正文;身份更换重新亮,读取副本与持久化同步清理,确认先记已见身份;旧无 key 退路无法识别直接替换。
|
||
- **控制室红线**:wt-console 固定首位、不可删除、唯一 console 标签不可关;隐藏项目不入网格。状态/计时/预览只镜像宿主,不为计时激活冷会话,不把完成标记当成功证明;业务临时持有结束释放。
|
||
- **更新检查/发布**:设置与控制室检查暂未去重,共用 updateCheck/lastUpdateCheck/skipVersion.v1,updateCache.v1 仅控制室。单次 8s、最多 3 次尝试;失败不可报最新。版本从 package.json 构建注入;新版本需 tag+Release,双资产固定名 dsh-worktable.tgz + 版本化名同 SHA。插件仅提示不自升级,安装/重启留给用户。
|
||
|
||
## link 加载兼容边界
|
||
|
||
- 不把旧宿主的祖先 node_modules junction 当通用修法。加载失败先核对宿主/profile/插件版本与第一条完整错误;不得直接创建更高层级链接、删除其目标目录或把社区桌面 resources/app 路径视为官方桌面的固定契约。
|
||
|
||
## 宿主历史补丁
|
||
|
||
- `02_process/upstream/utf16-picker-fix.patch` 是旧 picker 路径问题的存档,不代表当前宿主仍有此缺陷。先核对目标版本源码与复现,不自动套用或清理旧补丁。
|
||
|
||
## 安装 / 重启
|
||
|
||
- 注册:`dsh plugin --profile web add "link:<repo>/01_content"`(写 ~/.dsh,需用户授权)。
|
||
- 发布版安装(给用户):`dsh plugin --profile web add "https://github.com/Aisland-SJL/dsh-worktable/releases/latest/download/dsh-worktable.tgz"`(依赖每个 Release 的固定名资产)。
|
||
- Desktop:用实际安装目录 resources/runtime/cli/bin/dsh.cmd 对 desktop profile 安装;不得以网页 CLI 或不固定 npx 替代。安装前用户完整退出,安装后用户手动重开。
|
||
- bundle 启动时组合:网页重启 dsh web 并刷新;桌面完整退出/手动重开。不得自动重启正式宿主。
|
||
|