Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ Store 的 `validate-index.mjs` 仍然实现索引规则。它的 CI 原来比较

### Schema 地址固定为 docs 仓库的 raw 地址

两份 schema 的 `$id` 是它在 docs 仓库里的地址:
`https://raw.githubusercontent.com/Lithe-IDEA/lithe-plugin-docs/main/contract/v1/<文件名>`。
契约目录里每份 schema(包括子目录里的)的 `$id` 是它在 docs 仓库里的地址:
`https://raw.githubusercontent.com/Lithe-IDEA/lithe-plugin-docs/main/contract/v1/<目录内路径>`。

两边都对这个地址做严格检查:

- 主仓库的 `scripts/architecture/verify-shared-contracts.sh` 用常量 `published_plugin_schema_base` 要求 `$id` 完全相等。
- 主仓库的 `scripts/architecture/verify-shared-contracts.sh` 用常量 `published_plugin_schema_base` 要求目录下每个 `*.schema.json` 的 `$id` 完全相等。
- docs 仓库的 `contract.mjs` 要求每份 schema 的 `$id` 等于它自己的发布地址。

因此,如果主仓库改了地址而 docs 仓库没跟上,或者 docs 仓库里的文件不是从主仓库同步来的,CI 都会失败。
Expand All @@ -74,11 +74,15 @@ Store 的 `validate-index.mjs` 仍然实现索引规则。它的 CI 原来比较

副本只包含契约目录,`../` 开头的相对链接在 docs 仓库里会失效。所以契约 README 指向 `rust-core-api.md`、Agent Notes 的链接都写成 `https://github.com/1lck/Lithe-IDEA/blob/preview/...`,指向 SDK 的链接写成 lithe-plugin-docs 的地址。

这条规则适用于契约目录里的每个 Markdown 文件,不只是顶层 README。相对链接只能指向目录里的文件;指向目录(例如 `fixtures/`)也不行,因为 raw 地址取不到目录。要提到目录,写成代码文本即可。

两边都检查这条规则:

- 主仓库的 `verify-shared-contracts.sh` 拒绝离开目录或指向不存在文件的相对链接。
- 主仓库的 `verify-shared-contracts.sh` 检查目录下每个 `.md`,拒绝离开目录、指向目录或指向不存在文件的相对链接。
- docs 仓库的 `contract.mjs` 在同步和校验时也拒绝这类链接。

主仓库的检查必须和 docs 的同步规则一样严格。2026-11-01 同步 #1581 时,`proposals/toolchains/README.md` 里指向 `fixtures/` 的链接被 docs 拒绝:主仓库当时只检查顶层 README,而且允许链接指向目录,所以这个问题在合并前没被发现,只能再提一个 PR 修复后重新同步。

### `plugin.json` 里不能写 `$schema`

Core 解析清单时拒绝未知字段(serde `deny_unknown_fields`),schema 本身也是 `additionalProperties: false`。如果开发者按习惯加一行 `"$schema"`,插件会因为 `plugin.manifest.invalid` 装不上。所以指南要求在编辑器里按文件名关联 schema,例如 VS Code 的 `json.schemas`。是否在以后的契约版本里允许 `$schema` 另行决定:那需要提高能力版本,老版本 Lithe 会拒绝新格式。
Expand Down
18 changes: 13 additions & 5 deletions scripts/architecture/verify-shared-contracts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,19 @@ done
abort "native UI schema ID mismatch" unless native_schema.fetch("$id") == "#{published_base}/native-ui.schema.json"
abort "declarative manifests must use schemaVersion 2" unless schema.fetch("properties").fetch("schemaVersion").fetch("const") == 2
readme = File.read(File.join(root, "README.md"), encoding: "UTF-8")
# The mirror only holds this directory, so a relative link must resolve here.
readme.scan(/\]\(([^)\s]+)\)/).flatten.each do |target|
next if target.start_with?("#") || target.match?(%r{\A[a-z][a-z0-9+.-]*:}i)
path = File.expand_path(target.split("#").first, root)
abort "contract README link #{target} must be absolute or stay inside #{root}" unless path.start_with?("#{File.expand_path(root)}/") && File.exist?(path)
# The mirror only holds this directory and its sync rejects the same things: a relative
# link in any Markdown file must name a file here, and every schema names its mirror URL.
base = "#{File.expand_path(root)}/"
Dir[File.join(root, "**", "*.md")].sort.each do |document|
File.read(document, encoding: "UTF-8").scan(/\]\(([^)\s]+)\)/).flatten.each do |target|
next if target.start_with?("#") || target.match?(%r{\A[a-z][a-z0-9+.-]*:}i)
path = File.expand_path(target.split("#").first, File.dirname(document))
abort "#{document}: link #{target} must be absolute or name a file inside #{root}" unless path.start_with?(base) && File.file?(path)
end
end
Dir[File.join(root, "**", "*.schema.json")].sort.each do |path|
expected = "#{published_base}/#{File.expand_path(path).delete_prefix(base)}"
abort "#{path}: $id must be #{expected}" unless JSON.parse(File.read(path))["$id"] == expected
end
documented = readme.scan(/`(plugin\.[a-zA-Z.]+)`/).flatten
manifests = Dir[File.join(root, "fixtures", "*.plugin.json")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ not authorize replacing unrelated host commands.
| [query.schema.json](query.schema.json) | Query request/reply shapes |
| [resolution.schema.json](resolution.schema.json) | Resolver outcomes and structured reasons |
| [local.schema.json](local.schema.json) | Proposed extension of the machine-local document with directory pins |
| [fixtures/](fixtures/) | Illustrative contributions, queries, resolution outcomes, pins, and rejections |
| `fixtures/` | Illustrative contributions, queries, resolution outcomes, pins, and rejections |

Schemas describe JSON shape. Signature verification, duplicate-definition
registration, enabled-plugin ownership, path containment, executable evidence,
Expand Down
Loading