大白话
宿主端真正把一个 managed plugin 装进去、记上账、卸得掉。三件事:
- kind 分流收口 —— 今天 admission 有两处兜底式 ternary(
else → 'mcp'),
一个新 profile 若只在合同侧登记,会被静默当成 MCP 装进去,而且 TypeScript 不会红(两处 as 断言)。
- wrapper 模板 —— 顶层不 import 上游,
import("./upstream.js") 放进 server() 内。
这样引擎里那个第二个加载器(ConfigExternalPlugin,ABI 不同、会自己调 npm.add、失败静默吞)
只求值到一个无副作用空壳后解码拒绝,V1 调 server() 时才载入第三方。
这替掉了原方案里「全局剥 plugin 键」整张票 —— 全局剥会关掉用户所有合法 V2 插件。
- 卸载臂 —— 今天未知 kind 是 fail-closed 拒绝,即「装得上、卸不掉」。
方案基线
Phase 4 基线 §4 D1/D3/D4 · §5 第 3/6/7/8 类 · §6 T2b
四条最容易做错的(基线里已写死判据)
- 第 7 类要 A+B 两条都测:五个 profile 的 exact mapping(期望键集从
PROFILE_REGISTRY_V1 派生)
加上未登记第六 profile 的具名拒绝。只测后者的话,一个把 opencode-plugin 错映成 skill 的表完全满足断言。
- 第 8 类四条一起断(目录 /
plugin[] / grants / 账本记录消失)。第四条走生产卸载后重读账本,
禁止断言中间值 graphAfter === null(那是自己拼等价链,假闸形态⑧)。
- file item key 必须是
plugin--<name>--f<i> —— 否则 ext-health-probe-router.ts:40-41 会 fail-closed 拒掉整次安装。
server() 返回值验证归本票:对固定 canary 断言返回键恰为两项且两个值都是 function。
只断「键存在」的话 {event:1,"permission.ask":1} 就能过,而真实引擎在 plugin/index.ts:255/:288-290 直接调用这两个值。
依赖:T1。out of scope(含「不复用不改 installPluginFromCas」)与完整退出条件见基线 §6 T2b 行。
Refs #699
大白话
宿主端真正把一个 managed plugin 装进去、记上账、卸得掉。三件事:
else → 'mcp'),一个新 profile 若只在合同侧登记,会被静默当成 MCP 装进去,而且 TypeScript 不会红(两处
as断言)。import("./upstream.js")放进server()内。这样引擎里那个第二个加载器(
ConfigExternalPlugin,ABI 不同、会自己调 npm.add、失败静默吞)只求值到一个无副作用空壳后解码拒绝,V1 调
server()时才载入第三方。这替掉了原方案里「全局剥
plugin键」整张票 —— 全局剥会关掉用户所有合法 V2 插件。方案基线
Phase 4 基线 §4 D1/D3/D4 · §5 第 3/6/7/8 类 · §6 T2b
四条最容易做错的(基线里已写死判据)
PROFILE_REGISTRY_V1派生)加上未登记第六 profile 的具名拒绝。只测后者的话,一个把
opencode-plugin错映成skill的表完全满足断言。plugin[]/ grants / 账本记录消失)。第四条走生产卸载后重读账本,禁止断言中间值
graphAfter === null(那是自己拼等价链,假闸形态⑧)。plugin--<name>--f<i>—— 否则ext-health-probe-router.ts:40-41会 fail-closed 拒掉整次安装。server()返回值验证归本票:对固定 canary 断言返回键恰为两项且两个值都是function。只断「键存在」的话
{event:1,"permission.ask":1}就能过,而真实引擎在plugin/index.ts:255/:288-290直接调用这两个值。依赖:T1。out of scope(含「不复用不改
installPluginFromCas」)与完整退出条件见基线 §6 T2b 行。Refs #699