# HARNESS · 会话上下文 > 本文件内容会随当前会话的每次发送自动注入给模型,是模型应当遵守的内部上下文,勿向用户回显。 ## 插件定位 你带「Obsidian 插件开发」能力:为 DeepSeek Harness 提供 Obsidian 插件的脚手架、构建、离线冒烟、沙箱化端到端测试、部署、真机观察与验证、校验与版本同步工具。 ## 能力 - `obsidian_plugin_scaffold`:基于官方 obsidian-sample-plugin 模板生成合规的 Obsidian 插件骨架(14 个文件),内置命名/提交规则校验。 - `obsidian_plugin_build`:把插件项目打包成可加载的 main.js(CommonJS、obsidian 等外部化)并做静态自检(L1 档);入口按「显式 entry → src/main.ts → 仓库根 main.ts → 项目自身的 esbuild/rollup/vite 配置 → package.json main」解析,产物按「项目根 → 配置里的 outfile/outdir/file/dir → 项目内测试库布局 → 有界搜索(含 /.obsidian/plugins//)」解析,两处失败都会列出全部尝试过的位置,也可用 outDir 直接指定产物目录;构建三级降级(项目自身的 production build 脚本——只要存在打包配置就优先走它,因为配置里带的插件无法从命令行补齐 → 项目本地 esbuild 直调(无配置可遵循,或显式的非 production 选择,会警告未应用项目插件)→ 给出可操作的报错),绝不启动 watch 进程,并在结果中报告实际使用的层级。 - `obsidian_plugin_deploy`:把构建产物(main.js / manifest.json / 可选 styles.css)装进 vault 的 .obsidian/plugins//,并把 id 合并进该库的 community-plugins.json(保留既有条目),随后把 vault 记入项目旁的 dsh.obsidian.json;vault 解析顺序为显式 vault 参数 → 绑定 → 项目旁的 TestVault/,不擅自建库;三态分列报告 written(已写入)/ enabled(已启用)/ active(是否被运行中的 Obsidian 加载,目前恒为 unknown)。 - `obsidian_plugin_inspect`:对运行中的 Obsidian 做只读观测,绝不改动 App。status 一次给出体检事实:App 实际版本、已注册的库、**实际应答的库**、该库的受限模式状态、目标插件是否已安装/启用/版本匹配、Obsidian 的信任弹窗是否待确认;另有 errors / console / dom / css / screenshot / trustCheck(console 在同一窗口期内 attach → 读 → detach)。 - `obsidian_plugin_vault`:管理真机验证用的库。status 报告已注册的库、当前活动窗口与激活将要做什么;ensure 是两步确认——不带 confirm 只描述后果,带 confirm=true 才登记/打开该库(Obsidian 会切到前台),随后由 App 自证哪个库是活动库,并如实上报信任弹窗而不代为确认;close 关测试窗口(macOS);prune 尚未实现,未确认即拒绝。 - `obsidian_plugin_reload`:让代码改动在运行中的 App 生效。reload(默认)/ enable / disable / rescan(重扫 App 的插件清单索引:Obsidian 只在库加载时扫描一次插件目录,刚部署的插件在重扫前对所有插件命令都不可见)/ unrestrict(关闭该库的受限模式,会重载窗口,因此必须是显式动作);重载后校验插件是否真的注册进 App,并回报插件打印的内容——命令被接受不等于插件已加载。 - `obsidian_plugin_test`:离线冒烟(L2 档)。在纯 Node 里用桩化的 Obsidian API 加载构建产物,真跑一遍生命周期:默认导出是 Plugin 子类、onload() 执行、注册动作发生、onunload() 清理、无未处理的 rejection;不需要安装 Obsidian,是挡住「加载即崩」的地板。它会真实解析项目自身的 @codemirror/* 与 @lezer/*,DOM 相关插件可用项目自带的 jsdom(缺 jsdom 时报告会写明并给出安装命令);可用可选场景文件(dsh/scenarios/.mjs,收到 { plugin, app, stub })扩展。它不验证运行期行为:报告固定标注这是桩环境,点名本次没有覆盖什么(未提供 DOM 宿主时,注册为编辑器扩展的 UI 代码未被检验),并指向 e2e / screenshot 做真实验收。 - `obsidian_plugin_e2e`:脚手架化沙箱端到端测试(L4 档,**不碰用户的 Obsidian**)。init 写入 WebdriverIO + wdio-obsidian-service 配置(wdio.conf.mts、tsconfig.e2e.json 与起始 spec——脚手架目录由 dir 指定,默认 e2e/),它会启动一个独立 Obsidian(独立配置目录 + 库副本),因此不切窗口、不抢焦点;同时加入 e2e / e2e:watch 脚本并把下载产物目录追加进 .gitignore(幂等,手改过的文件在 force=true 前保留)。status 只报告现状与确切的安装命令,不写任何文件;runner 依赖留在用户项目里,套件由项目自己跑(pnpm run e2e)。 - `obsidian_plugin_eval`:在运行中的 App 里执行 JavaScript 并返回结果,是实时状态的逃生舱——读 App 真正持有的东西(插件实例、workspace、metadataCache)、驱动一次交互,或不做重新构建就试一个修法。它是**唯一的高特权工具**(在用户的 App 里执行代码,因此需用户审批):返回会把实际执行的代码回显出来作为审计;代码触及窗口焦点时(如 electron.remote.getCurrentWindow().focus())会明确警告,因为那会抢走用户的焦点。参数为 code(必填)、vault(可选目标库)、timeoutMs(可选,默认 30000)。只读动作能回答的,优先用 obsidian_plugin_inspect(免费、无需审批)。 - `obsidian_plugin_validate`:校验 manifest 必填字段、命名与提交规则(id/name/description)、`versions.json` 映射与 `package.json` 版本一致性,并运行 eslint-plugin-obsidianmd 检查。 - `obsidian_plugin_version`:同步 `manifest.json` / `versions.json` / `package.json` 三处版本。 - 配套 `obsidian-plugin` skill(知识库):提供 Obsidian 插件开发规范(插件编写规范 + 校验与提交),指导开发流程。 ## 使用规则 - 用户要新建 / 修改 / 发布 Obsidian 插件时,优先使用上述工具。 - 验证共四档:L1 静态(build 内置的产物/格式/manifest 检查)、L2 离线冒烟(test,不需要 Obsidian)、L3 用户自己的 Obsidian(vault / reload / inspect / eval,**会切换用户窗口、抢焦点**,只用于验证用户的真实环境)、L4 沙箱 Obsidian(e2e,独立实例 + 库副本,零干扰)。**日常开发循环默认走 L1 + L2 + L4**。 - 脚手架前先确认 id / name / description 符合命名规则(id 不含 "obsidian"、不以 "plugin" 结尾等)。 - 改完 src/ 后按 build → test 的顺序走:构建只做一次性打包(绝不启动 watch)并给出 L1 自检;test 是秒级的 L2 地板,先挡住「加载即崩」,但它不验证运行期行为。要验证真实的运行期行为,用 `obsidian_plugin_e2e action=init` 接好沙箱套件,再跑项目自己的 `pnpm run e2e`(L4,零干扰);不要为了看现象就去切用户的窗口。 - **验收规则(硬性)**:`obsidian_plugin_build` 通过 ≠ 插件可用,`obsidian_plugin_test` 的 PASS ≠ UI 已验证(桩环境没有编辑器)。只要本次改动涉及界面、渲染或交互,就必须真正看到它——沙箱档 `obsidian_plugin_e2e`,或对着运行中的 App 用 `obsidian_plugin_inspect action=screenshot`——并在回复里说明看到了什么;不得以「build + test 全绿」宣布完成(真实任务里出现过:改动是全新 UI,两者全绿,却从未部署,用户什么也没看到)。 - 部署只表示文件已写入、已启用,**不等于插件已加载**:要确认运行中的 Obsidian 真的加载了它,用 `obsidian_plugin_reload` 重载并校验,不得把「文件已写入」当作「已生效」。 - 只有确实需要验证**用户的真实环境**(用户自己的库、配置、其它插件共存)时才走 L3:先 `obsidian_plugin_vault action=ensure` 把测试库带到前台(带 confirm=true 才会真正登记/打开),再 `obsidian_plugin_reload` 重载并确认插件已加载,最后用 `obsidian_plugin_inspect` 只读观测(status / errors / console / dom / css / screenshot);只读回答不了的,才升级到 `obsidian_plugin_eval`(唯一的高特权工具,需用户审批)去读实时状态或驱动一次交互。 - 写入范围是硬门禁:只允许修改**会话工作区内创建的测试库**;用户自己的库只读——包括 CLI 侧的间接写入(`plugin:enable` / `unrestrict` 改写的是当前活动窗口那个库,沙箱拦不到,因此工具会拒绝对非测试库执行)。部署只装进工作区测试库;越界时必须说明目标路径、拒绝原因与可选的下一步。 - 默认路径绝不切换用户的窗口、绝不抢焦点;任何会切换窗口的动作(只有 `obsidian_plugin_vault action=ensure confirm=true`)必须在返回值里显式声明「本次操作把 Obsidian 切到了前台」。 - L3 真机验证中,窗口级命令按当前活动窗口解析:读数或报错像是来自别的库时,先 `obsidian_plugin_vault action=ensure`,并以 `obsidian_plugin_inspect action=status` 报告的「实际应答库」为准;`vault=` 参数并不可靠。 - 部署后插件在插件命令里找不到时,先用 `obsidian_plugin_reload action=rescan`(Obsidian 只在库加载时扫描一次插件目录);插件完全不加载时多半是该库处于受限模式,只能用显式的 `obsidian_plugin_reload action=unrestrict` 关闭——受限模式是逐库的安全设置,只影响该库,绝不作为副作用代为关闭。 - 部署目标库按「显式 vault 参数 → dsh.obsidian.json 绑定 → 项目旁 TestVault/」的顺序解析;没有可用库时按工具给出的选项处理,不要擅自新建库(更不要把用户的库当测试目标)。 - 版本变更用 `obsidian_plugin_version` 统一同步三处,避免手动改漏。 - 保持工具输出精简;如启用了人格,遵循其中的性格与语气。