Skip to content

docs(contracts): 删除工具链契约草案,已实现部分写进正式契约,测试改用内联数据 - #1752

Merged
xiaoyumuxi merged 2 commits into
previewfrom
docs/remove-toolchains-proposal
Nov 5, 2026
Merged

xiaoyumuxi merged 2 commits into
previewfrom
docs/remove-toolchains-proposal

Conversation

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator

为什么

shared/contracts/plugins/v1/toolchains/proposal/ 是工具链重写的设计草案,已实现和未实现的行为混在一起。它被逐字节同步到 lithe-plugin-docs 后,插件开发者看文档时分不清哪些现在能用。草案里已经实现的部分其实只有三块:后端协商、稳定失败码和错误回复规则。这次把这三块写进正式契约,删掉草案和它的 fixture。Core 测试原来读草案 fixture,现在改用内联数据。

改动

删除(13 个文件)

  • shared/contracts/plugins/v1/toolchains/proposal/ 整个目录:README.md、manifest.md、protocol.md 和 4 个 schema(local、manifest-contributions、query、resolution)。
  • shared/contracts/plugins/v1/fixtures/toolchains/proposal/ 整个目录:java-tool-definition.json、mise-provider.json、local.json、manifest-rejections.json、query-cases.json、resolution-cases.json。
  • 保留的 fixture 是 fixtures/toolchains/tool-definition.plugin.json 和 toolchain-provider.plugin.json,这两个是正式清单示例。

正式契约 shared/contracts/plugins/v1/toolchains/README.md

  • 状态段:去掉指向草案的句子,改为说明消费者迁移、原生查询生命周期与缓存、固定值保存和版本管理器插件都还没有规定;清单形状以 plugin-manifest.schema.json 为准。
  • 新增 ## Provider backend negotiation 一节,按 Core 现有实现写:
    • initialize 的 client capabilities 里带 experimental.litheToolchains: {versions:[1], providers:[已排序]}。只有声明了提供者、由插件拥有的会话才会收到。
    • 后端在 initialize 结果的 server capabilities 里回 {version:1, providers:[...]},providers 必须是 offer 的非空、不重复子集,其他字段忽略。答错一律一个都不启用,不会部分启用。
    • 成功后 Core 发出 toolchainProviders 运行时事件。
    • lsp.toolchainRequest 的输入、toolchains/query 方法和 Core 自己分配的 JSON-RPC ID。没有选中的提供者直接返回 not_supported / plugin.toolchain.providerUnavailable,不写请求。超时取值夹在 1–60000 ms,不传时用会话的请求超时。完成结果是 result.value:{id,response}。
    • 示例中的提供者 ID 用中性的 first / second,不写具体工具名。
  • 新增 ### Error replies 小节,替换原来指向草案 protocol.md#stable-failure-mapping 的链接:
    • error 必须恰好是 {code,message,data},data 是 {code,operationID,providerID} 加可选的 details。数字码要和 data.code 对应,两个 ID 要和请求 params 一致。message 非空、最多 1024 字节、不含控制字符。details 是对象,序列化后最多 4096 字节。违反任意一条都按 plugin.toolchain.invalidReply 拒绝。
    • 11 行的「JSON-RPC 数字码 | 稳定码 | 含义」对照表,与 rust/lithe-core/src/toolchain/query.rs 的 rpc_code 一一对应。
    • 写明安装缺失、版本不兼容、要求冲突都不是错误,要放在 result 里报告。
  • fixture 说明里补上测试共用的内联数据 toolchain_vectors.rs(用绝对 URL)。

契约总 README shared/contracts/plugins/v1/README.md

Core 测试(rust/lithe-core/src/tests/)

  • 新增 toolchain_vectors.rs,作为 pins、queries、resolution 三个测试模块共用的内联数据:
    • HOME、WORKSPACE 常量,以及私有的 MANUAL_HOME。所有路径都在 /opt/lithe-fixtures 下,测试既不创建也不探测这些路径。
    • local_pins():与原 local.json 内容相同,含 .、apps/web(手动固定 17.0.12)、.config/tools 三个固定。
    • query_request() / query_response():与原 query-cases.json 的 cases[0] 相同。
    • error_responses():每个稳定失败码生成一条错误回复。数字码在这里独立列出、不引用 query::rpc_code,所以测试检查的是映射本身。
  • mod.rs:注册 mod toolchain_vectors;。
  • toolchain_pins.rs:删除 fixture() 加载函数,改用 local_pins()。测试名 toolchain_pins_contract_fixture_inherits_the_nearest_ancestor 改为 toolchain_pins_inherit_the_nearest_ancestor,因为已经不读契约 fixture 了。
  • toolchain_queries.rs:去掉本地的 HOME/WORKSPACE 和 contract("queries") 分支,input() 改用 query_request()/query_response(),错误回复测试改为遍历 error_responses()。
  • toolchain_resolution.rs:去掉本地的 HOME/WORKSPACE 和 contract("query")、contract("local") 分支,改用共用的内联数据(保留 OLD)。
  • 测试断言没有改,覆盖范围不变。

Agent Note .agents/notes/proposed/architecture/2026-10-31-plugin-injected-toolchains.md

  • 「草案不授权提前迁移旧数据」改为「本提案不授权…」。
  • 阶段 1 行注明草案和 fixture 已于 2026-11-05 删除。
  • 原来描述草案位置的段落改写为删除记录:写明删除原因、已实现部分搬到了哪里、测试改用的内联数据,以及未实现部分只在本笔记跟踪、实现时再写进正式契约。
  • 「不能替代草案 schema 的专门校验或未来 Core 语义测试」改为「不检查 Core 语义,语义由下面的 Core 测试保护」。

语言门禁基线 scripts/architecture/language-specifics-baseline.json

  • 删除 10 条 /toolchains/proposal/ 条目(对应文件已删除)。
  • toolchain_queries.rs 16 → 15、toolchain_resolution.rs 91 → 90(内联后计数下降,按 ratchet 规则调低)。

验证

  • cargo test --manifest-path rust/Cargo.toml -p lithe-core --lib toolchain:99 passed,0 failed。
  • ./scripts/architecture/verify-shared-contracts.sh:通过。
  • ./scripts/agent-notes/verify-agent-notes.sh:通过(210 篇笔记)。
  • ./scripts/rust-core/verify-rust-core-comments.sh:通过。
  • ./.agents/skills/write-stable-tests/scripts/verify-test-stability.sh:通过。
  • 本仓库 20 个改动或相关 Markdown 文件中的 194 个相对链接逐个检查,0 个失效。
  • 改动的 4 个 Rust 文件跑过 rustfmt --edition 2021。build_systems.rs、declarative_plugins.rs、marketplace_plugins.rs、plugin_editor_resources.rs 的 rustfmt 差异是 preview 上原有的,本 PR 没碰。
  • verify-no-host-language-specifics.mjs --base origin/preview:只报新文件 toolchain_vectors.rs 的 words 0 → 9。这些词来自被删除的 local.json 和 query-cases.json。被删的 10 条草案基线条目合计 177 个计数,加上两个测试文件的 −2,整体净减 170。按维护者决定,本 PR 忽略这一项,不往基线加新条目。

合并后要做(lithe-plugin-docs)

本 PR 改了 shared/contracts/plugins/v1/,合并后在 lithe-plugin-docs 的同一个 PR 里完成:

  1. node scripts/contract.mjs sync --revision <合并后的 preview commit>。
  2. 修正仍指向草案的页面:
    • README.md 第 163、371 行的 toolchains/proposal/ 目录表行(中英各一)。
    • reference/capabilities-and-versions.md 第 112、271 行:litheToolchains 的链接改到 ../contract/v1/toolchains/README.md#provider-backend-negotiation。
    • reference/domains/toolchains.md 中文第 121、129–133 行和英文第 260、268–272 行:提案链接和 proposal fixture 列表。
    • reference/protocol-changelog.md 第 141 行是 docs(contracts): 插件契约 fixtures 按功能分目录并修正能力版本表 #1747 的历史登记,保持原样。
  3. 在协议更新记录登记本 PR(删除工具链草案,正式契约补充 litheToolchains 协商和错误回复规则),并在该 PR 描述中提及本 PR 作者请其核对。

- 删除 shared/contracts/plugins/v1/toolchains/proposal/ 和 fixtures/toolchains/proposal/
- 已实现的后端协商 litheToolchains、lsp.toolchainRequest、错误回复规则和 11 个稳定失败码写进 toolchains/README.md
- 新增 rust/lithe-core/src/tests/toolchain_vectors.rs,pins/queries/resolution 测试改用内联数据
- 同步契约总 README、工具链提案笔记和语言门禁基线
@ghfind-review ghfind-review Bot added the review: high ghfind author score; see https://ghfind.com label Nov 5, 2026
…ains-proposal

# Conflicts:
#	shared/contracts/plugins/v1/README.md
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review November 5, 2026 05:23
@xiaoyumuxi
xiaoyumuxi merged commit 5d38352 into preview Nov 5, 2026
5 of 21 checks passed
xiaoyumuxi added a commit that referenced this pull request Nov 5, 2026
- #1752 新增的 toolchain_vectors.rs 写死了 9 处工具名,Verify Host Language Specifics 在 preview 上失败
- 工具 ID 改从 fixtures/toolchains/tool-definition.plugin.json 读取,路径里的工具名换成中性的 tool
- toolchain_resolution.rs 复用 MANUAL_HOME,计数 90 -> 89,基线只调低这一行
xiaoyumuxi added a commit that referenced this pull request Nov 5, 2026
* feat(core): add editor provider decoding and v2 editor actions (API-25, API-27)

Core 新增 plugins.editorProviders.decode(注册、结果规范化、definition 合并)并扩展
plugins.editorActions.decode 到 version 2:额外图标、alternatives、点击结果 reveal。
宿主通过 lsp.startServer hostOptions.editor 声明图标、快照上限和路由的 Provider 类型,
getCapabilities 回显。未知 Provider 类型返回 unsupportedOption(-32018)。

Refs #1495

* feat(macos): host editor providers and v2 editor actions (API-25, API-27)

Refs #1495

- Declare the macOS editor host options (nine gutter icons, 1 MiB action
  source, seven provider types) and send them in the language-server
  start options so Core reports them through getCapabilities.
- Add the editor.providers permission label and the editor service
  `lithe/host/editor/registerProviders`: registrations are leased per
  plugin context, withdrawn on function withdrawal, session end and
  context close, and limited to 32 per plugin.
- Query matching providers concurrently with Core's per-type budgets and
  drop late, stale, failed or malformed answers; completion triggers only
  reach registrations that asked for the typed character.
- Supplement go-to-definition with plugin locations through Core's merge
  rule; the language server's answer is never replaced.
- Route editor action alternatives and the reveal result of a clicked
  action to the native navigation list.
- Bridge code lenses, document links, hover, completion, folding ranges
  and semantic tokens to the web editor behind opaque per-batch keys, so
  plugin targets and lens parameters never come from the page.

* feat(editor): draw plugin action lanes and add plugin editor providers (API-25, API-27)

Refs #1495

- Plugin editor actions get a left lane for navigation icons and a right
  lane for run icons, one marker per line and lane. A click opens a menu
  with each action followed by its alternatives (for example Debug after
  Run) and posts the opaque action and alternative keys.
- Add the nine icon names the macOS host offers plugins with light and
  dark SVGs, and check that every offered name has an SVG.
- Register hover, completion, code lens, folding range, semantic token
  and document link providers for all languages. They only supplement
  the language server: semantic tokens apply where no language-specific
  provider exists.
- Draw document links with opaque URLs of a private scheme and open them
  through a registered opener that asks the host, so a plugin-supplied
  URL (including command:) never reaches Monaco.
- Keep the page rules (range conversion, hover escaping, folding limits,
  semantic legend merge, action markers and menus) in pure modules with
  unit tests.

* test(macos): cover plugin editor providers and v2 editor actions (API-25, API-27)

* refactor(macos): keep plugin definition helpers out of the navigation extension (API-25)

AppModel+CodeNavigation grew to 619 lines and tripped the 600-line AppModel
extension limit in verify-service-boundaries.sh. The plugin-only helpers
(presenting plugin definitions, wrapping link availability) move next to
pluginDefinitionQuery. The log-exempt marker for the handled decode failure
now sits on the catch line, where verify-log-usage.mjs looks for it.

* docs(plugins): record editor provider and v2 editor action decisions (API-25, API-27)

Update the plugin API plan rows for API-25/26/27, rewrite the editor
extension Note around the shipped provider and action design, and register
the editor providers capability in the platform feature matrix (macOS
partial, Windows missing).

* fix(core): 编辑器 Provider 选择器的语言 ID 不区分大小写(API-25)

契约要求选择器条目不区分大小写匹配,宿主按小写比较语言 ID,
Core 解码注册时把 languages 转成小写再排序去重。
同时把两处测试里的 compactMap 移出 #require,避免宏展开后报
call can throw 的编译错误。

* fix(editor-providers): 修复编辑器 Provider 评审问题

- 修饰键悬停只保留最新一次插件定义查询,新悬停取消旧查询并让旧票据失效
- 只读预览不向插件询问定义,跳转前复查文档版本,结果在呈现处再确认仍然有效
- 用户可见错误改走 L10n.string
- 修正 EditorHostOptions 的 rustdoc 链接
- 插件编辑器 Provider 在宿主 Provider 之前注册,悬停探针的顺序稳定

* fix(editor-providers): 合并 fixtures 分目录后迁移编辑器 fixtures,导航复用语言服务器准备检查

- editor-providers、editor-actions-v2 fixtures 移入 fixtures/editor/,同步测试、契约脚本、README 和功能矩阵路径
- 转到定义的插件分支复用 languageServerIsPreparing,不在宿主导航代码里新增语言名
- plugin-editor-actions.ts 语言词计数降为 0,更新基线

* fix(toolchain-tests): 测试向量从共享 fixture 读工具 ID,修复 preview 上的宿主语言闸门

- #1752 新增的 toolchain_vectors.rs 写死了 9 处工具名,Verify Host Language Specifics 在 preview 上失败
- 工具 ID 改从 fixtures/toolchains/tool-definition.plugin.json 读取,路径里的工具名换成中性的 tool
- toolchain_resolution.rs 复用 MANUAL_HOME,计数 90 -> 89,基线只调低这一行
xiaoyumuxi added a commit that referenced this pull request Nov 5, 2026
- #1752 新增的 toolchain_vectors.rs 写死了 9 处工具名,Verify Host Language Specifics 在 preview 上失败
- 工具 ID 改从 fixtures/toolchains/tool-definition.plugin.json 读取,路径里的工具名换成中性的 tool
- toolchain_resolution.rs 复用 MANUAL_HOME,计数 90 -> 89,基线只调低这一行
xiaoyumuxi added a commit that referenced this pull request Nov 5, 2026
* feat(core): 插件函数中转的协议第 4 版与 pluginFunctions 清单校验

- 清单新增 requires.pluginFunctions:导出项 {id, version, context},调用声明 {id, version},context 第一阶段只有 workspace
- litheFunctions 协商版本新增 4,开放 lithe/host/functions/providers 与 lithe/host/functions/invoke
- 被调方收到由 Core 写入的 caller.pluginID(仅协议 4 以上)
- 新增 9 个 plugin.function.* 拒绝原因及对应数值错误码
- 旧的 wrongPlugin / recursiveCall 检查保持不变

* feat(core): relay plugin function calls between plugin backends

Add the cross-plugin function relay state machine (function_relay.rs) and
wire it into the LSP interface engine. A backend that negotiated
litheFunctions 4 can discover providers and invoke an exported function
through Core. Core checks declaration, export, enablement, version,
context, call chain, depth, per-caller concurrency and byte limits, and
propagates cancellation down the chain.

Refs #1495

* test(core): cover the cross-plugin function relay on real sessions

Scripted Python, Go and Rust plugin backends exercise the relay through the
engine: the call path with the Core-written caller field, discovery, every
refusal, cycles, cancellation down the chain, timeouts, loss of a caller or
callee, hot disabling, waiting for a provider the host starts, and provider
selection by workspace. The old recursiveCall and wrongPlugin refusals are
asserted unchanged.

* docs(contract): 插件函数跨插件调用的清单 schema、夹具与 README

- schema 新增 requires.pluginFunctions 与 pluginFunctions(exports 为 {id, version, context},calls 为 {id, version})
- 新增导出方、调用方两个有效夹具,以及 12 个无效清单用例
- README 新增“跨插件调用(协议第 4 版)”:私有与导出、发现与调用方法、调用链、caller 字段、错误码
- verify-shared-contracts.sh 校验 invocationCallers 与 relayErrors,并要求新错误码一码一号
- Core 夹具测试覆盖导出排序与 functions 宿主服务授权

* feat(macos): 接入插件函数中转的快照发布与被调方后端启动

Core 负责中转的全部判断,macOS 只做 I/O:

- MacPluginBackendSessions 在注册、工作区上下文变化、启用、禁用和包变更后,
  把清单里的 pluginFunctions 原样和上下文事实一起交给 Core
  (lsp.configureFunctionRelay),快照没变就不重复发布。
- 收到 functionProviderStartRequired 时,用普通的插件启动流程启动被调方后端,
  失败走既有的激活失败回报,等待上限由 Core 的 30 秒和会话初始化超时共同限定。
- PluginHostServiceDispatch 把 functions 服务列为 Core 直接应答的授权,
  不再被 supportedGrants 丢弃。
- hostCapabilities 增加 pluginFunctions,旧宿主仍会拒绝声明它的插件。
- 增加快照发布、被调方启动和 functions 授权的单测。

* docs(contract): 记录 lsp.configureFunctionRelay 命令

补充 Rust Core API 文档中的命令表和说明:载荷是插件的 exports/calls 与
工作区上下文快照,返回空对象,并链接到契约 README 的跨插件调用一节。

* docs(notes): 记录插件函数跨插件中转的第一阶段,并登记功能矩阵

- 已实现 Note(插件函数契约)新增决策 8:清单导出与调用声明、协议 4 的两个
  宿主请求、Core 检查顺序、调用链与取消、信任不传递与 caller 字段、被调方
  未运行时的启动请求、热激活、远程工作区,以及被否的方案和后果。
- 提议 Note(插件依赖与导出)只更新已落地的第一阶段,并写明依赖解析、版本
  冲突、依赖闭包、资源租约仍未实现,整篇 Note 仍留在提议中。
- 功能矩阵新增 plugin-cross-plugin-function-calls:macOS 部分实现、待原生
  验收,Windows 无插件后端宿主、行为不变;plugin-functions 指向新条目。

* fix(core): 中转调用的被调方失败使用独立数值错误码

被调函数返回错误(plugin.function.failed)和没有可用结果
(plugin.function.invalidResult)此前都回退到 -32603,与 Core 内部失败
plugin.host.failed 共用一个数值,调用方只凭数值分不清。改为 -32070 和
-32071,invalidResult 不再并入 failed;契约 README 与 fixture 同步。
同时删除未被使用的 plugin_functions 访问器。

* fix(toolchain-tests): 测试向量从共享 fixture 读工具 ID,修复 preview 上的宿主语言闸门

- #1752 新增的 toolchain_vectors.rs 写死了 9 处工具名,Verify Host Language Specifics 在 preview 上失败
- 工具 ID 改从 fixtures/toolchains/tool-definition.plugin.json 读取,路径里的工具名换成中性的 tool
- toolchain_resolution.rs 复用 MANUAL_HOME,计数 90 -> 89,基线只调低这一行

* fix(plugin-functions): 中转按会话分道写入,父调用显式关联,上下文失效即结束调用

- 每个目标会话一条写入车道,主工作线程只做规划;停止读取 stdin 的后端只拖住发往自己的写入
- 中转写入有截止时间(会话请求超时),超时后 monitor 让该会话失败(transportFailed/relayWrite)并结束进程
- lithe/host/functions/invoke 新增可选 parentOperationID:指定所服务的调用,调用链和取消只沿这一条走;
  不在调用方会话里运行的父调用返回 plugin.host.cancelled,格式错误返回 invalidParams
- 新快照让调用的工作区上下文关闭或换代时,等待中和运行中的调用都以 plugin.host.contextExpired 结束
- 运行中的调用在截止时间后再给 2 秒宽限,被调方仍不回答则以 plugin.host.timeout 结束并取消被调方
- functionProviderStartRequired 复用已有事件构造函数,新文件不再出现宿主语言词
- Swift 解码失败的 try? 和 Rust 的 let _ = 补 log-exempt 标注
- 契约 README、function-protocol fixture、Note 同步;热激活描述更正
- 新增引擎级测试:阻塞后端不拖住其他调用、父调用限定取消、未知/已结束/格式错误的父调用、上下文关闭或换代

* test(macos): 跨插件调用测试按 #1747 的新目录读取 backend fixtures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: high ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant