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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Use the schemas and existing listings as implementation references. A shortened

### Static catalog facts

Catalog counts are file-derived, not usage statistics. Do not author views, downloads, ratings, Stars, install counts, or runtime health. Missing publisher evidence remains unknown. A listed release is not a live latest-version query. Preserve the upstream release identifier; do not invent a three-part version to fill a missing fact. New team localization fields and two-part pointer versions must wait until the matching client contract is released before being published to the shared catalog. Regenerate bootstrap archives through the client repository's synchronization tools, never by editing ZIP contents manually.
Catalog counts are file-derived, not usage statistics. Do not author views, downloads, ratings, Stars, install counts, or runtime health. Missing publisher evidence remains unknown. A listed release is not a live latest-version query. Preserve the upstream release identifier; do not invent a three-part version to fill a missing fact. New team localization fields and two-part pointer versions must wait until the matching client contract is released before being published to the shared catalog. Until then, an upstream identifier the released contract does not admit, such as a bare revision number `50`, stays out of `latestVersion` and `release`: keep the release unknown rather than reshaping the identifier. Regenerate bootstrap archives through the client repository's synchronization tools, never by editing ZIP contents manually.

### Local skills

Expand All @@ -115,6 +115,8 @@ The `retired` list identifies former built-in skills that clients may retire at

An external skill uses `skills/<id>/entry.json` to describe its upstream source, presentation, maintainer, category, license, and redistribution terms. Skill listings require an inline SVG `icon`. Supported source kinds are `git`, `web`, and `zip`; external listings count toward `manifest.stats.totalSkills` but do not belong in the built-in skill index.

The raw pointer must pass the [exported skill client schema](schemas/market-skill-entry.client.schema.json) before sidecar validation. A client skips any entry that fails it, so the listing disappears for its users while the manifest still counts it. `latestVersion` accepts numeric `x.y` or `x.y.z` and maps to `release.version`; the sidecar's `versionScheme` must be the one the client derives from that value, which is `opaque` for `x.y`. The sidecar must also agree with the pointer on `category`, `tags`, `riskLevel`, and `requiredClientVersion`, and cannot add `skillType` or `compatibleAgents`, which a pointer does not declare. On any difference the client rejects the whole sidecar and the listing becomes listing-only.

A collection groups multiple upstream skills under one listing, with a declared `children` inventory for discovery. Keep the children's metadata in the parent's sidecar. Each child has its own `skill + parentId + id` identity and release fact; never infer a child's version from its parent, whose version may be unknown.

See the [Lark Suite CLI entry](skills/larksuite-cli/entry.json) and [sidecar](skills/larksuite-cli/catalog-metadata.v1.json). The [collection generator](scripts/gen-collection-children.py) derives children from upstream `SKILL.md` files; its `--check` mode verifies reproducible, pinned collections without rewriting entries.
Expand Down Expand Up @@ -161,7 +163,7 @@ The [catalog metadata schema](schemas/catalog-metadata.v1.schema.json) covers pr
- **Evidence paths follow the content.** `license.evidencePath`, `compliance.licenseEvidencePath`, and `compliance.noticePath` are relative to the item directory for vendored content, and the files must exist. For pointers they refer to the upstream snapshot; offline validation cannot fetch that evidence and warns about claims against unpinned sources.
- **Unknown is a valid fact.** Use explicit `known` / `unknown` states. A known day uses `YYYY-MM-DD` with `precision: "day"`; a known second uses an RFC 3339 UTC timestamp ending in `Z` with `precision: "second"`. Never fill an unknown release or catalog timestamp with the current date, clone time, or synchronization time.

The agent and team client schemas are generated compatibility snapshots. Their `$comment` records the upstream source commit and blob. Refresh them from the corresponding TypeScript exports when compatibility changes; do not weaken them or substitute sidecar-only validation.
The agent, skill, and team client schemas are generated compatibility snapshots. Their `$comment` records the upstream source commit and blob. Refresh them from the corresponding TypeScript exports when compatibility changes; do not weaken them or substitute sidecar-only validation.

## Localization

Expand Down
6 changes: 4 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

### 静态目录事实

条目数量来自文件清单,不是访问量或使用量。禁止静态记录 Stars、下载量、评分、安装数量或运行健康度;证据缺失保留未知。收录版本不代表联网查询的最新版本,应保留上游原始发布标识,不能为填补缺失捏造三段版本。新的团队本地化字段及两段指针版本必须先有已发布的兼容客户端,再进入共享目录。Bootstrap 压缩包由客户端仓库的同步工具生成,不能手工修改 ZIP 内容。
条目数量来自文件清单,不是访问量或使用量。禁止静态记录 Stars、下载量、评分、安装数量或运行健康度;证据缺失保留未知。收录版本不代表联网查询的最新版本,应保留上游原始发布标识,不能为填补缺失捏造三段版本。新的团队本地化字段及两段指针版本必须先有已发布的兼容客户端,再进入共享目录。在此之前,已发布契约不接受的上游标识(如纯修订号 `50`)不写入 `latestVersion` 和 `release`,发布版本保持未知,不能改写标识去迎合格式。Bootstrap 压缩包由客户端仓库的同步工具生成,不能手工修改 ZIP 内容。

## 快速开始

Expand Down Expand Up @@ -115,6 +115,8 @@ uv run scripts/i18n/validate-i18n.py

外部技能使用 `skills/<id>/entry.json` 描述上游来源、展示信息、维护者、分类、许可证和再分发方式。技能条目必须提供内联 SVG `icon`,来源支持 `git`、`web` 和 `zip`。外部条目计入 `manifest.stats.totalSkills`,但不进入内置技能索引。

指针原始数据必须先通过[导出的技能客户端 Schema](schemas/market-skill-entry.client.schema.json),再进行 sidecar 校验。客户端会跳过未通过的条目,用户看不到它,而清单仍把它计入数量。`latestVersion` 接受 `x.y` 或 `x.y.z` 形式的数字版本,并映射到 `release.version`;sidecar 的 `versionScheme` 必须与客户端据此推导的结果一致,`x.y` 对应 `opaque`。sidecar 的 `category`、`tags`、`riskLevel` 和 `requiredClientVersion` 也必须与指针一致,且不能添加指针无法声明的 `skillType` 和 `compatibleAgents`。任何差异都会让客户端拒绝整份 sidecar,条目退化为仅收录。

技能集合通过一个市场条目组织多个上游技能,并声明 `children` 清单供发现和展示。子技能的元数据保留在父条目的 sidecar 中;每个子技能都有独立的 `skill + parentId + id` 身份和发布事实。父条目的版本可以未知,不得用父版本推断子技能版本。

参考[飞书 CLI 条目](skills/larksuite-cli/entry.json)及其 [sidecar](skills/larksuite-cli/catalog-metadata.v1.json)。[集合生成器](scripts/gen-collection-children.py)从上游 `SKILL.md` 提取子技能,`--check` 模式只验证固定版本、可复现的集合,不重写条目。
Expand Down Expand Up @@ -161,7 +163,7 @@ uv run scripts/i18n/validate-i18n.py
- **证据路径跟随实际内容。** 对随仓库分发的内容,`license.evidencePath`、`compliance.licenseEvidencePath` 和 `compliance.noticePath` 相对于条目目录解析,且文件必须真实存在。对指针,这些路径指向上游快照;离线校验无法获取该证据,并会对未固定来源的证据声明给出警告。
- **未知也是有效事实。** 使用显式 `known` / `unknown` 状态。已知日期使用 `YYYY-MM-DD` 和 `precision: "day"`;已知秒级时间使用以 `Z` 结尾的 RFC 3339 UTC 时间戳和 `precision: "second"`。不得用当前日期、克隆时间或同步时间填补未知的发布或目录时间。

智能体与团队客户端 Schema 是生成的兼容性快照,其 `$comment` 记录上游来源提交和 blob。兼容性变更时,应从相应 TypeScript 导出重新生成,不得放宽契约或用仅校验 sidecar 的方式替代。
智能体、技能与团队客户端 Schema 是生成的兼容性快照,其 `$comment` 记录上游来源提交和 blob。兼容性变更时,应从相应 TypeScript 导出重新生成,不得放宽契约或用仅校验 sidecar 的方式替代。

## 多语言维护

Expand Down
4 changes: 4 additions & 0 deletions docs/upstream-health-213-remediation.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,7 @@ Still open after this round:
- For the next review: at the current wecom-cli pin, `wecomcli-pptx/references/templates/anti-ai-slop.md` names the source-available pptx skill in anthropics/skills as one source of a reworded checklist.

Third-party programs and live account services were not executed.

## Later correction (2026-10-31)

`skill/reverse-engineer-anything` recorded upstream revision `50` in `latestVersion` and `release.version`. The client pointer contract admits only numeric `x.y` or `x.y.z`, so clients dropped the listing from their index, and the catalog validator did not check skill pointers against that contract. The repin and its review stand. The listing now declares no version (`release: unknown`), and the validator checks skill pointers against the [exported client schema](../schemas/market-skill-entry.client.schema.json).
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "DesireCore Official Market",
"version": "1.5.21",
"version": "1.5.22",
"schemaVersion": "1.1.0",
"supportedLocales": [
"zh-CN",
Expand Down
229 changes: 229 additions & 0 deletions schemas/market-skill-entry.client.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"id",
"name",
"stewardship",
"license",
"redistribution",
"source"
],
"properties": {
"id": {
"type": "string",
"description": "条目唯一标识符,使用小写连字符格式,如 \"flyai-skill\"",
"pattern": "^[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",
"minLength": 3,
"maxLength": 160,
"pattern": "^[0-9]+\\.[0-9]+(?:\\.[0-9]+)?$",
"not": {
"pattern": "[\\r\\n]"
},
"description": "目录收录的上游原始数字版本,允许 1.0 与 1.0.0;canonical 原样保存。旧 runtime latestVersion 另按既有 SemVer 兼容规则投影,不改变实际安装来源或准入。"
},
"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",
"web",
"zip"
],
"description": "内容来源类型:git(仓库)/ web(网页或文件)/ zip(打包产物)"
},
"repoUrl": {
"type": "string",
"description": "源仓库 Git URL 或资源 URL,如 https://github.com/desirecore/skill-foo.git"
},
"repoBranch": {
"type": "string",
"description": "源仓库分支名称,默认 main(kind=git 时有效)",
"default": "main"
},
"path": {
"type": "string",
"pattern": "^(?:$|(?![A-Za-z]:[\\\\/])(?![\\\\/])(?!.*(?:^|[\\\\/])\\.\\.(?:[\\\\/]|$))[^\\u0000]+)$",
"description": "内容在源仓库中的安全相对子路径,如 \"skills/foo\";为空表示仓库根目录。禁止绝对路径、盘符与 .. 路径段。"
},
"ref": {
"type": "string",
"description": "锁定的 commit SHA / tag,用于可复现安装;为空表示取分支 HEAD"
},
"sha256": {
"type": "string",
"pattern": "^[0-9a-fA-F]{64}$",
"description": "web/zip 资源原始响应体的 SHA-256;能力自动安装要求用它绑定发现时的不可变字节。"
}
},
"additionalProperties": false
},
"requiredClientVersion": {
"type": "string",
"description": "此条目要求的最低客户端版本(semver),低于此版本时提示升级",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
},
"riskLevel": {
"type": "string",
"enum": [
"low",
"medium",
"high"
],
"description": "技能的风险等级,决定操作是否需要用户确认和权限检查"
},
"children": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"path"
],
"properties": {
"id": {
"type": "string",
"description": "子技能 ID,同时是安装到 skills/ 下的目录名,使用小写连字符格式。长度上界不只是目录名卫生:该 id 会被拼进对外诊断的 `children.<id>.<field>`,而诊断 `field` 有 Ajv `maxLength`——不限长等于把第三方仓库的一个字符串变成详情端点 500 的开关(同步器出口另有截断兜底)。",
"pattern": "^[a-z0-9-]+$",
"maxLength": 64
},
"path": {
"type": "string",
"description": "子技能在源仓库中的子路径,如 \"skills/lark-im\"",
"minLength": 1
},
"name": {
"type": "string",
"description": "默认显示名称(源 locale),本地化变体见 i18n"
},
"i18n": {
"type": "object",
"description": "按 locale 提供的本地化展示元数据(仅 name/shortDesc,轻量)",
"additionalProperties": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "该 locale 下的显示名称"
},
"shortDesc": {
"type": "string",
"description": "该 locale 下的简短描述"
}
},
"additionalProperties": false
}
},
"version": {
"type": "string",
"description": "市场登记的子技能版本(semver),上游 SKILL.md 缺根级 version 时作为兜底",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
}
},
"additionalProperties": false
},
"minItems": 1,
"description": "合集子技能清单。存在即表示本条目是合集(源仓库内有多个平级技能),安装时由用户勾选装哪几个;与 source.path 互斥。缺省时按单技能条目处理。"
}
},
"additionalProperties": false,
"$comment": "Generated from desirecore/desirecore packages/schemas/src/market.ts#marketSkillEntrySchema at commit b7d11e919882ec2cfe3087104e0bf06c10493c83 (v10.0.195), source blob 9fc439c9c662ea086ab8a8024c9e4830b084653b. Keep the complete client contract; regenerate from that export instead of editing fields manually."
}
Loading
Loading