mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-09-05 17:03:49 +08:00
## 变更 / What
市场此前只有 `agents` 与 `skills` 两类条目。本 PR 加入**团队(teams)**条目类型,并上架第一条真实团队
listing。
The market supported only `agents` and `skills`. This PR adds a
**teams** entry type and lists the first real team.
## 一、支持团队条目类型
「支持一种新条目类型」实际涉及 4 组共 11 个文件,比表面看到的多:
**客户端契约快照**
- 新增 `schemas/market-team-entry.client.schema.json`,用 esbuild 打包客户端
`packages/schemas/src/market.ts` 后导出生成。用同样方法重新生成
`market-agent-entry.client.schema.json` 验证过管线——字节完全一致(含属性顺序),确认不是手工誊抄。
**Sidecar schema**
- `identity.kind` 枚举加 `team`;新增 `$defs.teamSpec`;接入 `spec.oneOf` 与
kind→spec 派发
**校验器(工作量主要在这里)**
- `scripts/catalog/validate_catalog_metadata.py`:`load_legacy`
原先硬编码只认两个根目录。抽出 `CATALOG_ROOTS` 常量同时驱动允许的父目录集合与错误文案;按 kind 分派客户端 schema
校验;`teams` 进 stats 与 `--require-complete` 覆盖统计;把**严格 provenance
比对**与「可安装 pointer 必须自带不可变 ref」两道门禁扩展到团队
- `scripts/i18n/validate-i18n.py`:**它独立重算计数并逐个校验 `entry.json`**,不接团队会漏校
- `.github/workflows/i18n-validate.yml`:变更检测的 grep 不含 `teams/`——**一个只改
teams 的 PR 会报「无 i18n 相关变更,跳过校验」然后零校验通过**
- 测试:`test_validate_catalog_metadata.py` 29→47,`test_validate_i18n.py`
9→17
**顺带修正一条本就不对的规则**:`icon` 此前被要求「每个 entry.json 都必须有非空内联 SVG」,但运行时 schema 里
`marketAgentSchema` 与 `marketTeamSchema` **都没有 `icon` 字段**(只有 skill
有)。也就是说这条规则对 Agent pointer 同样在强加死重量,只因本仓库暂无 agent pointer 条目而未暴露。改为
`ICON_RENDERED_KINDS = {"skill"}`,agent/team 声明 icon
时给**警告**而非错误,文案说明「下一个维护者会以为改它能改变卡片」。
## 二、上架合同审查团队
`teams/contract-review-team/`(`entry.json` + sidecar)。
**团队条目是 fork 指针卡,不分发正文**:市场只存展示元数据 + git-only `source`,真实定义(`team.json`
/ `members.json` / `shared/`)在 `source.repoUrl` 指向的仓库里。安装即
`forkTeam`,更新即 `git pull`——组合固定,因此**没有** `installPolicy` /
`updatePolicy`。
| 字段 | 值 | 依据 |
|---|---|---|
| `source.ref` | `73cd87a9901cc548871927e9d5dbec8e4cc6c2b1` | v0.1.1
的**完整 SHA**。tag 不是可复现 pin,validator 有测试专门拒绝 |
| `latestVersion` | `0.1.1` | 上游真实 tag,与 `release.version` 交叉校验 |
| `license` | `MIT` | 上游仓库真有 LICENSE,已在 pinned ref 的快照中复验 |
| `redistribution` | `source-pointer-only` |
市场从不打包团队正文,只给指针——这是交付形态,与许可证宽松与否无关 |
| `requiredClientVersion` | `10.0.137` | 六个成员都声明了 `FileDigest`
内置工具,它随该版本发布 |
| `memberCount` / `memberNames` | 6 / 5 名 | schema 规定前者**含**组长、后者**不含**
|
| `availability` | `listing-only` | 见下 |
**`availability` 为什么不是 `installable`**:四项证据满足两项(不可变 pin ✓、已知 license
✓),缺的 `reviewedAt` 与 `governance.compliance`
本质是**一次尚未发生的治理审查**——需要具名方在具体日期针对这个确切 ref 审过许可合规、第三方内容与商标使用。没发生的事不能写进目录。
补充一个事实:本仓库**零个 sidecar 有 `compliance` 块,29 个 pointer 条目全是
listing-only**,`installable` 路径从未在任何真实条目上走过。这不阻止安装——fork 由 `source` 驱动。
**`license.evidencePath` 的基准此前是未定义的**:schema 只说
`safeRelativePath`,没规定相对谁。仓库里仅有的两个先例(`guizang-ppt`、`presentation-forge`)都是
vendored 技能,LICENSE 物理上在条目目录里。按那个读法,pointer 条目写 `evidencePath`
断言的是市场目录下有该文件——对 pointer 永远不成立。新增 `license-evidence` 规则按条目形态分派:vendored
要求文件存在(error),pointer 要求条目已 pin(warning),两种读法写进 README。
## 校验 / Validation
```
test_validate_catalog_metadata.py 47 tests OK
test_validate_i18n.py 17 tests OK
test_collection_generator.py exit 0
validate_catalog_metadata.py --require-complete
0 error, 116 warning (agents=1, teams=1, publishableSkills=62, sidecars=64)
validate-i18n.py / --online 0 error, 116 warning
translate.py --check exit 0
gen-collection-children.py --check exit 0
```
116 warnings 即加入团队之前的基线——**本条 listing 贡献 0 个警告**。
真实条目上的反向控制(跑在 rsync 副本上,仓库保持干净):
```
source.kind=zip → team-entry-schema (error)
install/updatePolicy 出现 → team-entry-schema (error)
requiredClientVersion 漂移 → legacy-consistency (error)
memberCount 漂移 → legacy-consistency (error)
provenance ref 漂移 → legacy-consistency (error)
可安装但无不可变 ref → installable-evidence (error)
evidencePath 在未 pin 的 pointer → license-evidence (warning)
```
另用**客户端真实校验器**(`parseMarketTeamEntry`,不是快照)验证条目通过,且多写一个字段会被拒。
## 公开信息边界 / Public information boundary
全树扫描无新增命中。团队内容使用「某某科技(北京)有限公司」这类标准中文占位。
---------
Co-authored-by: yi-ge <mizan57533@gmail.com>
220 lines
8.3 KiB
JSON
220 lines
8.3 KiB
JSON
{
|
||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||
"type": "object",
|
||
"required": [
|
||
"id",
|
||
"name",
|
||
"stewardship",
|
||
"license",
|
||
"redistribution",
|
||
"source"
|
||
],
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "团队条目唯一标识符,采用与 team.json#id 相同的团队 slug 规则(不允许首尾连字符),保证市场 ID 天然是一个合法团队目录名。",
|
||
"pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$"
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "默认显示名称(源 locale),本地化变体见 i18n"
|
||
},
|
||
"category": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"pattern": "^[a-z0-9-]+$",
|
||
"description": "市场项目分类(slug 格式),由仓库 categories.json 定义"
|
||
},
|
||
"tags": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"description": "标签列表,用于搜索和分类"
|
||
},
|
||
"icon": {
|
||
"type": "string",
|
||
"description": "市场列表展示的内联 SVG 图标。**只有 Skill 卡片渲染它**——marketAgentSchema 与 marketTeamSchema 都没有 icon 字段,Agent 与团队卡片一律走 avatar,条目声明了 icon 也不会显示。Pointer 技能将其随离线元数据返回。"
|
||
},
|
||
"latestVersion": {
|
||
"type": "string",
|
||
"description": "市场登记的最新版本(semver)",
|
||
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
||
},
|
||
"i18n": {
|
||
"type": "object",
|
||
"description": "按 locale 提供的本地化展示元数据(仅 name/shortDesc,轻量)",
|
||
"additionalProperties": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"description": "该 locale 下的显示名称"
|
||
},
|
||
"shortDesc": {
|
||
"type": "string",
|
||
"description": "该 locale 下的简短描述"
|
||
}
|
||
},
|
||
"additionalProperties": false
|
||
}
|
||
},
|
||
"maintainer": {
|
||
"type": "object",
|
||
"required": [
|
||
"name",
|
||
"verified"
|
||
],
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"description": "维护者名称,如 \"DesireCore Official\""
|
||
},
|
||
"verified": {
|
||
"type": "boolean",
|
||
"description": "是否官方认证维护者,认证后显示蓝色勾选标记"
|
||
},
|
||
"account": {
|
||
"type": "string",
|
||
"description": "维护方账号标识,如 GitHub 组织/用户名 \"desirecore\""
|
||
},
|
||
"url": {
|
||
"type": "string",
|
||
"description": "维护方主页或仓库 URL"
|
||
}
|
||
},
|
||
"additionalProperties": false
|
||
},
|
||
"stewardship": {
|
||
"type": "string",
|
||
"enum": [
|
||
"official",
|
||
"partner",
|
||
"community",
|
||
"pointer"
|
||
],
|
||
"description": "维护方分类:official(官方)/ partner(合作伙伴官方)/ community(社区已收录)/ pointer(仅指针,不分发内容)"
|
||
},
|
||
"license": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "许可证:SPDX id(MIT/Apache-2.0/MIT-0…)或特殊值 not-declared / source-available / packaged-distribution"
|
||
},
|
||
"redistribution": {
|
||
"type": "string",
|
||
"enum": [
|
||
"allowed",
|
||
"source-pointer-only",
|
||
"verify-package-terms"
|
||
],
|
||
"description": "再分发策略:allowed(可分发)/ source-pointer-only(仅指针,安装时拉取)/ verify-package-terms(需核验条款)"
|
||
},
|
||
"source": {
|
||
"type": "object",
|
||
"required": [
|
||
"kind",
|
||
"repoUrl"
|
||
],
|
||
"properties": {
|
||
"kind": {
|
||
"type": "string",
|
||
"enum": [
|
||
"git"
|
||
],
|
||
"description": "团队只支持 git 源:安装是 fork 团队仓库、更新是 git pull,zip / web 无法表达这两个动作。"
|
||
},
|
||
"repoUrl": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "团队 git 仓库的 HTTPS 克隆地址,如 https://github.com/desirecore/team-contract-review.git"
|
||
},
|
||
"repoBranch": {
|
||
"type": "string",
|
||
"description": "团队仓库分支名称,默认 main。安装时会真的按这个分支克隆;必须是合法分支名(不带 refs/ 前缀、不以 - 开头),否则安装失败关闭而不是静默改装默认分支。",
|
||
"default": "main"
|
||
},
|
||
"ref": {
|
||
"type": "string",
|
||
"description": "锁定的 commit SHA / tag,用于可复现安装;为空表示取分支 HEAD。只接受**完整 40 位 SHA-1** 或标签名:缩写 oid 会随仓库增长变歧义、也远比完整 SHA 容易被构造碰撞,而降级 git 后端根本不解析它。安装时会按该 ref 克隆并读回真实 HEAD 逐字复核,不一致就中止整个安装——一个不被兑现的锁比没有锁更危险,因为它会被信任。"
|
||
}
|
||
},
|
||
"additionalProperties": false,
|
||
"description": "团队 fork 源。**这是团队条目的核心**:安装端点用 repoUrl + repoBranch 调用 forkTeam,更新用同一仓库 git pull。"
|
||
},
|
||
"requiredClientVersion": {
|
||
"type": "string",
|
||
"description": "此条目要求的最低客户端版本(semver),低于此版本时提示升级",
|
||
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
||
},
|
||
"avatar": {
|
||
"type": "object",
|
||
"required": [
|
||
"t",
|
||
"bg"
|
||
],
|
||
"properties": {
|
||
"t": {
|
||
"type": "string",
|
||
"description": "头像显示的文字(通常为一个汉字)",
|
||
"maxLength": 2
|
||
},
|
||
"bg": {
|
||
"type": "string",
|
||
"description": "头像背景 CSS 渐变值,如 linear-gradient(135deg, #007AFF, #005ECB)"
|
||
},
|
||
"image": {
|
||
"type": "object",
|
||
"description": "图片头像:市场仓库中该条目目录内的位图(如 \"assets/avatar.webp\")。存在且文件可读时优先于 t + bg 渲染,否则自动回落——所以 t 与 bg 仍为必填,它们是确定的回落形态。仅支持 PNG / JPEG / WebP。注意:这是**市场展示**元数据,与安装后 agent.json 的 avatar.image 是两套,安装时不迁移。",
|
||
"required": [
|
||
"path"
|
||
],
|
||
"properties": {
|
||
"path": {
|
||
"type": "string",
|
||
"description": "相对于该市场条目目录的图片路径。禁止绝对路径和 .. 路径穿越",
|
||
"minLength": 5,
|
||
"maxLength": 240,
|
||
"pattern": "^(?![\\\\/])(?![A-Za-z]:)(?!.*(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$)).+\\.(?:png|jpe?g|webp)$"
|
||
}
|
||
},
|
||
"additionalProperties": false
|
||
}
|
||
},
|
||
"additionalProperties": false
|
||
},
|
||
"supervisorName": {
|
||
"type": "string",
|
||
"description": "组长(supervisor)Agent 的显示名称,仅用于卡片与详情页展示;真实组长以团队仓库 team.json#supervisor 为准。"
|
||
},
|
||
"supervisorAgentId": {
|
||
"type": "string",
|
||
"description": "组长 Agent ID(展示与去重用)。只是发布者声明,不作为安装期白名单依据。",
|
||
"pattern": "^[A-Za-z0-9_-]+$"
|
||
},
|
||
"memberCount": {
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"description": "团队成员总数(**含组长**),用于卡片上\"N 名成员\"的展示;不参与任何安装校验。"
|
||
},
|
||
"memberNames": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"maxItems": 32,
|
||
"description": "成员显示名预览列表(不含组长),用于卡片上的成员缩略展示;不保证与仓库成员完全一致。"
|
||
},
|
||
"requiredSkills": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
},
|
||
"maxItems": 128,
|
||
"uniqueItems": true,
|
||
"description": "团队声明的必需 Skill ID,用于安装前向用户提示前置条件;真实校验由安装后的团队 capability audit 执行。"
|
||
}
|
||
},
|
||
"additionalProperties": false,
|
||
"$comment": "Generated from desirecore/desirecore packages/schemas/src/market.ts#marketTeamEntrySchema at commit 947d9f32c6c81ebe5ece78f6295155814c888a22, source blob d6b361d149773e7384babe3011d86d25ded4e493. Keep the complete client contract; regenerate from that export instead of editing fields manually."
|
||
}
|