两类文档来源不同,处理方式也不同: - system-proxy-runtime-control-spec.md、terminal-command-address-spec.md 是 to-spec 技能的原样产物(英文模板小节标题,无标题与日期头)。其内容已发布为 Issue #72 / #73,人类需要的信息已由同日提交的无后缀中文文档承载;在仓库里再 存一份,等于同一份规格有两个事实来源。删除后仍可从 git 历史追回。 - user-plugin-*-spec.md 四份来自 improve-codebase-architecture 会话:该技能把 报告写进 OS 临时目录、不写 docs/design/,因此这四份是模型模仿仓库既有 -spec.md 旧例命名(“猜测旧例”而非技能指令)。去掉后缀后仓库不再有该样板, 后续模型少了可模仿的命名来源。四份保留原名主体,内容不动。 影响面:这六份文件全仓库零入站引用(含 docs/ 内部),移除与改名都无需改写链接。 docs/design/ 现为 12 份,无一带 -spec 后缀,与 AGENTS.md 的定位一致。 有意不做:不加“docs/design/*.md 必须带可解析 日期:/状态: 头”的确定性检查。 AI 输出本就无法保证规范化;更关键的是这类文档的“状态”只描述某次改进上下文, 不跟踪现状,把它当可校验字段是假精确。日期是写作时点的事实,两回事。
14 KiB
有效插件目录:实现规格
日期:2026-10-04。
状态:候选 1 的领域规则已确认并授权实现。当前交付范围为目录、持久化、接线与安全检查事实;用户明确选择管理 UI 后续实现。候选 2 的表单接入与候选 3 的提交接入是功能落地所需的相邻工作,不表示通用架构重构。此文记录本任务规格,当前实现仍以代码为准。
已确认的行为
- 用户维护当前 macOS 用户的本机插件名称到可执行文件路径的映射;只持久化用户新增与 override,不复制 managed 默认值。
- 名称区分大小写、精确匹配。新增名称去除首尾空白并拒绝空名称;导入的名称引用保持原样。
- 用户映射优先于同名托管插件。override 不可用仍阻断该名称,不静默退回 managed;删除 override 恢复当前 app 的 managed 默认值。
- 路径必须为绝对文件路径,允许符号链接。保存新增或修改的路径时要求目标当前存在且可执行;不运行插件,不解析 shell 命令、PATH 查找、相对路径或带参数的命令。
- 用户映射的有效来源不继承 managed 文件的版本、许可证或签名声明。
- 改名视为删除旧映射、添加新映射,不改写服务器配置与订阅。路径修改影响引用同一名称的所有服务器,包括订阅服务器。
- 保存后发布有效目录、刷新激活候选并异步收敛。运行失败不撤销已保存映射。
- 不监控同路径二进制替换,不据此自动重启。新的激活或代理启动重新检查文件;用户可关闭再开启代理使用同路径的新文件。
- 安全检查异步提供隔离标记、签名与策略评估事实;不因这些事实拒绝保存或激活,不自动移除隔离标记、重签或修改系统策略。检查失败或不适用不等于安全或禁止运行。
当前代码的摩擦
| 当前位置 | 当前事实 | 需要改变的内容 |
|---|---|---|
Domain/ManagedPluginProviding.swift |
名称到路径的现有 seam 已被校验和激活使用;bundle adapter 检查文件可执行性 | 保留窄解析 seam,托管供应链事实不承担整个有效目录的职责 |
Domain/ActivationStateMachine.swift |
校验和生成运行条目分别调用 provider | 同一次派生读取同一个捕获快照,避免两次查询读到不同映射或文件检查事实 |
App/CatalogWorkflow/CatalogWorkflow.swift |
直接以静态 managed 集合分类、加载参数和校验保存 | 改为有效目录事实;未知引用仍可保留,已映射引用可编辑参数 |
App/CatalogWorkflow/CatalogWorkflow+URI.swift |
.unknown 不更新插件引用及选项 |
不再用托管身份代表可编辑性;保留未解析引用的无损编辑行为 |
App/MainApp.swift、App/ProxyRuntimeController.swift、App/DiagnosticsWorkflow/DiagnosticsWorkflow.swift |
生产读取者独立构造 bundle provider | 组合根装配一次插件目录 module,并向各读取者提供相同已提交映射来源 |
App/CatalogCommitCoordinator.swift |
捕获服务器目录快照;只在目录提交时安排同步 | 映射变更有自己的保存入口;复用运行时,不伪造服务器目录提交 |
App/ProxyRuntimeController+Convergence.swift |
preparation 代次使旧派生失效;运行配置字节不变可跳过部署 | 发布映射时使旧插件派生失效,保留有效值不变的幂等行为 |
Module 与 interface 提案
以下名称为拟议代码标识符;实际文件布局可随实现收敛。目标是让覆盖、文件事实与提交时序获得 locality,而非给每条规则创建 shallow module。
有效插件目录 module
拟议 PluginCatalog 是组合根拥有的单一 module。只向调用者提供:
- 捕获当前有效目录快照,供表单、校验、激活及诊断读取。
- 保存一组明确的用户映射变更,包括新增、更新、删除与改名组合。
- 观察已提交目录变更及安全检查事实。
调用者不自行合并 managed 与用户映射,不直接改磁盘文件,也不拼接保存、刷新 projection 和运行重启步骤。存储与 macOS 检查 adapter 在 module 内接线;生产文件 adapter 和测试确定性 adapter 构成实际 seam。
拟议 PluginCatalogSnapshot 是只读值,包含已提交映射代次与各已知名称的有效来源、路径可用性及独立的托管发布事实。快照不表示文件永久可执行,也不表示远端连接、SIP003 兼容性或系统许可得到保证。
名称到路径的 interface 仍保持一个查询。建议把 ManagedPluginProviding 一次性改名为 PluginExecutableResolving,并让快照满足该 interface;不长期保留一层兼容转发 module。已有 NoManagedPluginProvider 与测试 provider 按同一 seam 调整。
解析结果由有效目录保留原因事实:未映射、文件缺失、非可执行文件、文件检查失败。现有激活 interface 可以继续把失败归入本地插件不可用原因;细化原因不要求改动 sslocal 的运行配置结构。
快照与文件事实
- 捕获快照时对已知名称的有效路径检查一次;查询仅查捕获结果。校验与运行条目生成共享该快照。
- 已有快照用于一次 projection 或派生,不缓存成整个会话的永久可用性结论。
- 新激活、代理启动和映射发布后的重校验捕获新快照;只检查有效路径,不因为用户 override 失效而检查并选用 managed 路径。
- 符号链接保存用户选定的路径;文件检查跟随链接,不能用链接本身的存在性替代目标的可执行性。
- “存在且可执行”还必须排除目录;路径作为进程参数或系统调用参数传递,不能拼入 shell 命令。
- 不通过快照承诺消除文件检查与实际执行之间的文件变化;最终执行结果仍属于运行时事实。
持久化与提交
建议增加独立 plugins.json,放在既有用户配置目录,通过 AtomicFileWriter 原子写入。文件只包含格式版本和用户名称—路径条目;managed 清单仍随 app 发布。
一组变更作为一次保存单位:规范化并验证本次新增或修改条目 → 在已提交副本上应用变更 → 原子写盘 → 发布新映射代次 → 重建有效目录与服务器 projection → 安排异步运行收敛。
- 同名新增不得静默覆盖已有用户条目;更新已有条目必须由明确更新操作表达。对 managed 名称新增用户条目就是 override。
- 改名包含旧名删除和新名新增,作为一次原子变更;新名称冲突不允许悄悄覆盖另一用户条目。
- 只校验本次新增或修改路径。既有失效映射允许保留,也允许删除,不能因为另一个文件失效就阻止用户修复无关条目。
- 文件可执行性检查失败拒绝本次新增或修改;安全预检不延迟或决定保存成功。
- 存储失败不发布快照、不刷新 projection、不安排运行收敛。运行失败保留保存结果。
- 无变化保存可以不产生新代次;重新激活与重新开启代理仍检查当前文件。
读取异常的实现建议:文件不存在表示没有用户映射;文件损坏、不可读或未知格式版本不能伪装成空映射,因为这可能意外启用被覆盖的 managed 文件。应保留错误事实,阻断依赖插件的自动派生并允许用户显式修复;不使用插件的服务器不受此错误影响。此失败处理已由用户确认。
映射变更与运行状态收敛
- 映射发布立即让后续读取捕获新代次,并使旧的运行派生失效;仅在异步任务结束时忽略结果不足以保护旧运行契约写入。
- 复用
ProxyRuntimeController现有 preparation 代次与收敛入口。映射、服务器目录、规则及代理意图变化仍受同一运行时失效检查约束,不能为插件另造一套独立进程部署逻辑。 - 最新保存发生在运行任务中途时,保存可完成;在途任务不能晚到写入旧路径,随后安排最新目录的收敛。
- 目录重校验使用最新已提交服务器目录和本次插件快照;不修改订阅字段、服务器身份、凭据引用或分享格式。
- 未受影响的活动目标不因新增无关名称而重启;有效运行配置不变时沿用现有幂等判断。
- 活动组仍可跳过失效成员;目标没有可用服务器时沿用现有目标失效处理,不引入静默服务器替代。
- 表单只更新插件事实,不重载并覆盖未保存的服务器字段或参数草稿。
macOS 安全检查 adapter
拟议 MacOSPluginInspection 把系统检查输出转换成结构化事实,而非把命令输出直接呈现或导出。
- 文件下载隔离标记:存在、未发现、读取失败。
- 签名:有效、未签名、签名无效、检查不适用、无法判断。脚本及其解释器不等同于一个 Mach-O 文件,不能默认要求所有可执行文件都有 Developer ID 签名。
- 系统策略评估:接受、评估拒绝、不适用、检查失败。独立工具的评估上下文限制必须保留,不能把
spctl的非零退出统一映射成实际执行禁令。 - 只读检查在后台执行,带超时与受控输出大小,不随每次视图重绘重复执行;无须新建定时轮询或文件监控。
- 结果绑定映射代次、名称和所检查的目标文件事实。映射或目标文件变化后,旧结果不得显示在新目标上;检查完成时重新核对相关事实,不能把文件身份未确认的结果当成当前结果。
- 保存后可安排检查;新的激活 / 启动检查及启动失败后的复查不得直接执行用户插件作为探测。
- 普通退出、超时或被 signal 终止不足以证明安全策略阻止。仅有明确证据才能显示确认阻止;证据不足显示启动失败和辅助检查事实。
- 插件由 sslocal 启动,现有 GUI / agent 不一定直接得到其系统执行拒绝原因;本轮不为了强行归因解析任意原始日志,也不修改上游 sslocal。
- 本机 UI 可显示路径并提供 Finder 定位;诊断报告仍不导出路径、原始检查输出或插件参数。用户插件没有自报版本验证,因此有效来源不能继承 managed 的版本声明。
依据(2026-10-04 查阅,属于外部能力资料,不表示已有实现):
相邻 module 的接入范围
候选 2:调整 PluginSelection 与 PluginSectionState,让服务器引用与实际来源独立;读取有效目录的名称选择和可用性。未知引用无损保留;对应映射新增后加载原有参数;映射删除后不删除引用及钥匙串参数。保留现有 PluginOptionsDraft 与 CredentialWriteJournal。
候选 3:映射提交 module 负责保存、发布与安排收敛;复用现有原子写盘与运行时,不先建立跨所有设置的通用协调框架。具体管理页面位置、编辑交互与中英文提示文案尚未确认,不属于当前已确认的候选 1 领域合同。
验证矩阵
测试通过调用者使用的 interface 观察行为,新增 hostless 测试默认使用 Swift Testing;临时目录及文件只占用进程私有资源。
| 验证面 | 必须观察到的行为 |
|---|---|
| 有效目录 interface | managed 默认值、新名称、大小写区分、同名 override、删除恢复当前 managed、失效 override 不回退 |
| 文件 adapter | 普通可执行文件、目录拒绝、缺文件、权限丢失、符号链接可用及失效、文件检查失败 |
| 保存 interface | 路径规范与名称冲突、改名原子性、只校验改动条目、保存失败不发布、无变化幂等、重新加载恢复用户映射 |
| 读取异常 | 缺文件与损坏不同;损坏不使 managed override 消失;显式修复后恢复插件派生 |
| 服务器表单 interface | 用户插件创建 / 编辑、unknown 映射后参数可见、删除映射保留引用和参数、订阅仍只读、刷新不覆盖草稿 |
| 激活 interface | 快照路径进入运行配置、组跳过失效成员、无有效成员沿用失败处理、不修改分享与订阅内容 |
| 收敛 interface | 保存完成不等待运行健康;运行失败不撤销保存;A→B 连续保存旧运行写入受抑制;无关映射不重启;关闭代理期间旧任务不复活代理 |
| 检查 adapter 的确定性替身 | 隔离 / 未签名 / 拒绝为提示;不适用及失败不误报;超时不挂起保存;旧结果不覆盖新目标 |
| 诊断 interface | 来源与有效路径选择一致;用户文件不继承 managed 版本;路径与原始输出不进入报告 |
继续保留有价值的 bundle 文件检查与清单锚点测试;新增有效目录行为覆盖后,移除仅固化静态 managed 分类的重复断言,不叠加一套测试保留相互矛盾的旧合同。
hostless 测试不证明真实 Gatekeeper 行为。实现后需单独用本机受控夹具核实签名、隔离与独立工具评估的呈现;实际 sslocal 子进程、native UI 与系统安全提示分别报告,不能用 fake 检查通过替代。
实施顺序与审阅点
- 有效目录值、用户映射模型、文件 adapter 与持久化;先证明解析优先级、文件事实和读取异常。
- 在组合根统一注入;校验与激活捕获固定快照,诊断读取相同来源事实。
- 表单引用接入与提交发布;证明异步过期任务不能写回旧运行配置。
- macOS 检查 adapter 与提示事实;管理 UI 布局和本地化另行确认后接入。
- 聚焦测试、既有相关回归、构建与独立本机证据。若新增工程结构,遵循 XcodeGen 的
project.yml,不手改.xcodeproj。
本文没有引入插件下载 / 安装 / 升级、插件参数语义验证、文件监控、自动重签或系统安全策略修改;没有修改 frozen Legacy,也没有发布 GitHub Issue 或推送。实现按用户授权在当前分支作本地提交。