Skip to content

Spec: 元协议协商内核(Negotiation)

状态:Draft v0.15(社区讨论稿,非官方标准) 产出物:schemas/negotiation-report.schema.json 读者提示:这份 spec 一半写给实现协商器的宿主开发者,一半写给在 CI 里消费协商报告的工具作者;§4 给全三种结局的完整示例。

这份文件定义"协商"这件事:拿一份插件 manifest 和一份宿主自述(Host Descriptor),不运行任何插件代码,静态算出"能不能装、能不能跑、要不要先问用户",并产出一份机器可读报告。它是领域无关的纯函数,不依赖 dsh 就能测试。

1. 适用范围

本文规定协商纯函数的签名、匹配规则、三种判定和报告格式。以下内容不在本文:

2. 规范性定义

2.1 函数签名与纯度

text
negotiate(manifest, hostDescriptor, registrySnapshot) → report

协商必须是纯函数:

  • 无 I/O、无网络访问、不读时钟与随机源;相同输入必须产生相同报告;
  • 不得 import dsh / Cordis / 任何宿主产品代码——CI 里不装 dsh 也必须能跑;
  • registrySnapshotregistry/ 条目的冻结快照,作为输入传入(v0.15 即三条标准条目);协商器不得自行从规范正文发明条目。

内核只做三件事:解析参与者声明、解析 apiVersion + kind 契约引用、做 requires/supports 匹配。

2.2 前置条件

进入协商前,manifest 与 Host Descriptor 必须已分别通过各自的 schema 校验(即生命周期 validate 阶段已通过,见 lifecycle.md)。协商器对非法输入的行为不作规定——工具应当在调用协商前先校验。

2.3 匹配规则

按顺序执行三类检查:

  1. Facet 检查:对 manifest facets 中每个 facet,其 apiVersion 必须出现在 Descriptor apiVersions[facet] 数组中;不满足的记入 unsupportedFacets
  2. 契约检查:对 requires.contracts 每项,在 Descriptor capabilities 中找 apiVersionkind 双双精确相等的条目(坐标规则见 VERSIONING.md)。required 契约无匹配 → 记入 missingRequired;optional 契约无匹配 → 记入 degradedOptional
  3. 敏感检查:对所有匹配成功的声明(含 subscriptions 引用的事件),查 registry 快照的敏感级别;标记为需授权的记入 awaitingAuthorization。optional 且缺失的声明不进入此项——缺失即降级,无需授权。

2.4 判定规则

verdict条件含义
rejectedmissingRequiredunsupportedFacets 非空拒载:安装/激活之前明确拒绝
pending-authorization无拒绝项,且 awaitingAuthorization 非空宿主支持,但需用户或策略授权后才能激活
compatible以上都不是静态协商通过(degradedOptional 可能非空)
  • required 缺失 → 拒载,且报告必须携带用户能看懂的人话原因:说明插件需要什么、当前环境缺什么。示例样式:"该插件需要图形界面能力,当前终端不支持"。只输出坐标串、没有人话解释的报告不合规。fixture:conformance/fixtures/negotiation/rejected-missing-required/expected-report.json
  • optional 缺失 → 降级:verdict 仍为 compatible,缺失项列入 degradedOptional,插件按声明过的降级路径运行(语义见 manifest.md §3.7)。fixture:conformance/fixtures/negotiation/degraded-optional/expected-report.json
  • 待授权不是拒绝pending-authorization 表示"授权即可用";授权流程本身(何时问、如何记)是宿主 authorize 阶段的职责(见 lifecycle.md),不属于本纯函数。
  • 报告到市场五态的映射规则(声明兼容 / 等待授权 / 已实测 / 不兼容 / 未知,且不得互相升级)见 host-descriptor.md §3,本文不复述。

2.5 协商报告格式

报告是单个 JSON 对象,schema 见 schemas/negotiation-report.schema.json

字段类型必填含义
reportVersionstring报告格式版本,v0.15 必须等于 "0.15"
verdictstringcompatible / rejected / pending-authorization 之一
messagestring人话结论;rejected 时必须含 §2.4 要求的可读原因
missingRequiredarray缺失的 required 契约坐标({ apiVersion, kind }
degradedOptionalarray缺失的 optional 契约坐标(降级项)
awaitingAuthorizationarray待授权的敏感声明坐标
unsupportedFacetsarrayfacet API 版本不匹配项({ facet, requiredApiVersion, supportedApiVersions }

宿主、市场、启动器、CI 必须消费同一份报告格式——社区此前的插件校验报告(qing3a / dsh-plugin-verify 的格式诉求)已并入本格式,不再单独存在(背景见 decisions/round-1)。

3. 示例输入

以下示例共用同一份 Descriptor(坐标为示意,以 Registry 定案为准):

json
{
  "descriptorVersion": "0.15",
  "id": "org.example.dsh-tui",
  "apiVersions": { "host": ["v1alpha1"] },
  "execution": { "environment": "node", "trustMode": "trusted-in-process" },
  "capabilities": [
    { "apiVersion": "commands.dsh/v1alpha1", "kind": "Command" },
    { "apiVersion": "storage.dsh/v1alpha1", "kind": "LocalStorage" }
  ]
}

4. 三种结局的完整示例

4.1 兼容(compatible

manifest 声明 required storage.dsh/v1alpha1 + optional messages.dsh/v1alpha1。storage 匹配成功;messages 未匹配但为 optional → 降级。

json
{
  "reportVersion": "0.15",
  "verdict": "compatible",
  "message": "静态协商通过;可选的消息观察能力不可用,插件将按声明的降级路径运行。",
  "degradedOptional": [
    { "apiVersion": "messages.dsh/v1alpha1", "kind": "MessageObserver" }
  ]
}

4.2 拒载(rejected

manifest 声明 required x-org.example.gui.panel/v1alpha1(kind: Panel),Descriptor 未提供该坐标。

json
{
  "reportVersion": "0.15",
  "verdict": "rejected",
  "message": "该插件需要图形面板能力(x-org.example.gui.panel),当前终端宿主不支持,无法安装。",
  "missingRequired": [
    { "apiVersion": "x-org.example.gui.panel/v1alpha1", "kind": "Panel" }
  ]
}

4.3 待授权(pending-authorization

manifest 声明 required messages.dsh/v1alpha1(kind: MessageObserver),Descriptor 支持该坐标,但 registry 条目标记其为敏感(sensitivity: high,见 registry/events/messages.dsh-v1alpha1.md)。

json
{
  "reportVersion": "0.15",
  "verdict": "pending-authorization",
  "message": "宿主支持该插件,但它需要观察消息内容,等待用户授权后才能激活。",
  "awaitingAuthorization": [
    { "apiVersion": "messages.dsh/v1alpha1", "kind": "MessageObserver" }
  ]
}

5. 错误与边界情况

情况规定行为抓住它的 fixture / 测试
manifest / Descriptor 未过 schema 校验不进入协商(validate 阶段已拒)manifest 与 host-descriptor 的 invalid fixtures
required 契约无匹配verdict rejected,人话说明缺什么negotiation/rejected-missing-required/
facet apiVersion 不在宿主支持列表verdict rejected,记入 unsupportedFacetsnegotiation/rejected-unsupported-facet/
optional 契约无匹配verdict compatible,记入 degradedOptionalnegotiation/degraded-optional/
敏感声明匹配成功但未授权verdict pending-authorizationnegotiation/pending-authorization/
契约坐标不在 registry(含 x-org.* 私有坐标)不是错误:照常按坐标匹配;宿主未声明即不匹配negotiation/rejected-missing-required/
requires.contracts 为空且无敏感声明verdict compatiblenegotiation/compatible/
同一输入多次协商必须产出逐字节相同的报告(纯度)suites 确定性断言

6. 对应 fixtures 清单

fixtures 由后续任务创建。每个用例目录含 manifest.jsonhost-descriptor.jsonexpected-report.json 三个文件:

  • conformance/fixtures/negotiation/compatible/
  • conformance/fixtures/negotiation/degraded-optional/
  • conformance/fixtures/negotiation/rejected-missing-required/
  • conformance/fixtures/negotiation/rejected-unsupported-facet/
  • conformance/fixtures/negotiation/pending-authorization/

7. 变更记录

版本变更
v0.15首版成稿。协商内核重构为领域无关元协议(契约可拔插、独立版本化,本轮讨论处置见 decisions/round-2);判定收敛为 compatible / rejected / pending-authorization 三种;机器可读报告格式定稿,社区校验报告诉求并入本格式。

社区 Draft,非 dsh 官方标准 | MIT License