习慈羊xiciyang
联系
订阅
正在读取订阅状态…

团队里管插件,先管退出:准入、失败、退出是一张表

团队里第 3 个人装了一个插件,第 1 个人的会话行为跟着变了:工具多了一屏、注入的规则多了一段,却没人说得清是谁加的。

判断标准只有一条:能不能干净地退掉。写给负责 agent 平台的团队负责人,以及准备往生态里发插件的人。

审批救不了团队:一条记录只绑定一个字节,改字就作废

先说三张表,再给一条判据:准入表问将来能不能退,失败表是退出路径的演练,退出表把演练变成命令。

最常见的治理方式是审批:谁装了什么,记一笔。这个做法有一个结构性缺陷:记录绑定的是某个版本的内容哈希,内容改一个字节,记录就失效,而失效之后没有任何机制能自动恢复。

于是流程变成:改稿、审批失效、发布被拦、找人重新点一次。改动越频繁,人工确认越多,最后所有人学会绕过它。

站点发布踩过这个坑:审批台账里的哈希对不上,部署链第一步就断,只能人工补一次点击。博客后来改成脱敏扫描,结论由字节派生,改了就重扫,不再有「失效」状态。插件治理是同一个形状:凭证会失效,函数不会。准入需要的是一段可执行的检查。

准入表:4 个问题没答完,就不该装

装之前问四件事,答不上来就停在「补什么」:

  1. 每步成本多少? 工具声明与组目录各占多少字符,装前装后各测一次。本机现状是 92 个工具、74,008 字符固定文本[3]。
  2. 崩了会拖垮谁? 能卡住主进程、能吃掉上下文的,要求它提供进程外运行方式。
  3. 怎么退? 一条能直接执行的命令。
  4. 谁维护? 一个能叫出名字的人。

权限也要分层。本机默认是 danger-full-access 加审批关闭,方便单人开发;团队场景里这个默认值等于把风险平摊给每个人,应当按会话收紧到工作区写、必要时只读。权限要每次会话重新给。

失败表:坏插件先隔离,一次崩溃只损失一个能力

团队最怕的是插件出错让整场会话起不来。

本机的做法是 fail-soft:坏插件在装配阶段被隔离(写进禁用补丁),其余插件照常启动;隔离列表可查,也能一键恢复[2]。它还有一层进程外包装,内核补丁失效时自己解析崩溃、自己写隔离、退避重拉。

这套机制的价值在于把故障从「整场停摆」降成「一个能力缺失」。但它不清理数据:插件被隔离了,它的配置、数据目录、写过的补丁都还在。失败表因此要加一列「残留状态」,否则下一次装回来会撞上旧状态。

退出表:装之前就必须有回滚点

退出表是三张表里唯一必须在装之前填的。

回滚点用 tar 快照,不用会重建产物的备份工具:那类工具先清理再构建,构建一失败就把产物一起删掉[4]。删目录前先确认目标不是符号链接,依赖目录里的链接不会出现在依赖声明里。删完 grep 三处:工具名、配置键、被它改过的层。

配置是重点。覆盖按 id 整段替换,不做深合并;删插件不等于删掉它留下的整段配置。本机把停用项列在插件 exclude 清单里,每条附一行理由,删插件时要连这一行一起删。

删除的顺序也要反过来:先摘配置,再删目录,最后清依赖链接。中途状态如果指向不存在的目录,下一次启动就会报一个看不懂的错。

团队治理的三张表:准入、失败、退出

图 1:三张表的三列内容;最后都落到「每一行都有可执行的回滚动作」。

结论:三张表其实是 1 条判据,退不掉的能力不该进团队

准入、失败、退出看起来是三件事,实际是同一张表的三列:准入问的是「将来能不能退」,失败是「退出路径的演练」,退出是「把演练变成命令」。

这条判据还能反过来用:一个插件如果说不清怎么退,就不该进团队环境;一个团队如果只有审批没有退出命令,那审批只是记录了谁负责背锅。

也可以用它给治理排优先级。先填退出表,成本最低、收益最大;再填失败表,把已知的崩溃形状变成隔离规则;最后填准入表,因为前三张表会让准入标准变得具体。

发布门槛:3 条硬条件,README 说得再好也不算

如果团队还要往生态里发插件,门槛必须是静态可检查的。

三条硬条件:声明了 bundle 补丁;写清 engines.dsh 版本约束;仓库公开且能被静态检查[1]。三者缺一,发布后别人装不上,或者装上了一个没人能核对的包。

检查可以机械跑:许可证白名单、密钥与绝对路径扫描、README 的安装 / 用法 / 配置 / 兼容 / 许可五节是否齐全。判定只有三种:可发、补什么、不许发。缺证据就停在「补什么」,不要用「大概没问题」放行。

发布顺序也有讲究:先发一个最小可验证件当探针,跑通安装与卸载,再发主推能力。生态里的包已经很多,先发的那个包会替你回答「有没有人真的需要它」。

发布门槛:静态可检查、机械 lint、探针、旗舰

图 2:四道门槛,前三道都能写进 CI;第四道等探针的反馈。

反例与边界:3 种治理方式会把风险放大

把审批当治理。 审批记录只在内容不变时有效,频繁改动会把它变成死锁;治理要的是可执行检查,不是签名。

所有人全权限。 单人开发的默认值搬到团队,等于让每个人都可能改坏所有人的会话;权限要按会话给。

把「没崩过」当隔离。 没出过故障不代表有隔离能力。判据是:把插件弄崩一次,主进程还能不能起来。没有演练过的失败路径,不算路径。

边界也要说清。两个人的小团队,可以只填退出表,准入用一句约定代替;人数再多、能力面再杂,三张表才都有必要。单人自用不在此列:个人开发者更适合按三笔账(上下文、热重载、卸载)来算。

行动:一张表 + 3 条命令,从下一装开始用

表就三列:能力、回滚动作、维护者。每装一个填一行,回滚动作写成可复制的命令。

# 1. 装前快照
tar -czf plugin-backup-$(date +%F).tgz <插件目录>

# 2. 装后记录工具面增量
node deploy-dsh/tool-budget-gate.mjs

# 3. 卸载后查三处残留
grep -rn "<工具名前缀>" ~/.dsh/profiles/web/cordis.patch.yml ~/.dsh/config.yaml

三条命令对应三张表的入口:快照是退出表,预算是准入表,grep 是失败表的残留清理。团队里谁执行都可以,结果一样。

收尾:3 篇写完,判据只剩一条

三篇的路径是同一条:先判断能力该不该进模型上下文,再量三笔账决定形态,最后用可退出性决定它能不能留在团队里。所以判据只有一条:每一份能力都要为它占用的每一步、以及它退出时要动的地方,付出可解释的代价。

参考文献

[1] DeepSeek Harness. 打包与安装插件[EB/OL]. 开发文档, 2026. https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish

[2] DeepSeek Harness. 插件与生命周期[EB/OL]. 开发文档, 2026. https://deepseek-harness.github.io/deepseek-harness/develop/framework/

[3] 本站. 从字节数账:上下文预算到底花在哪[EB/OL]. 2026-10-17. https://xiciyang.com/blog/token-audit-from-bytes/

[4] 本站. 备份在,回滚却从未生效[EB/OL]. 2026-10-11. https://xiciyang.com/blog/backup-was-there-rollback-never-ran/

评论

填个昵称就能发,不需要注册或登录