Yige b18073cb97 docs(wecom-assistant): 补使用说明并重新 pin / add USAGE.md and repin (#136)
## 中文

企业微信助手的市场详情页「使用说明」区此前为空。内容仓库

[`desirecore-agent/wecom-assistant@047928a`](047928afe1)
新增 `USAGE.md`,本 PR 把条目重新 pin 过去。

### 为什么要写这两条

它们都是**装之前**该知道、且**装完也改不了**的边界,正是 `USAGE.md` 的定位(ADR-143:与 `fullDesc`
分开,不进模型上下文)。

**1. 群聊历史目前仅对 ≤10 人企业开放。** 官方错误码 `853001` 的释义原文如此。实际触发返回相邻的 `853006`:

```
errcode: 853006
errmsg:  this tool is not available for your corporation
```

措辞是 **for your
corporation**,不是「机器人未开通某品类」——所以让用户去找管理员开通品类是无效动作。本机实测复现,同一凭证下其余 12
个服务域全部正常,`chat` 是唯一被拒的域。上游 `WecomTeam/wecom-cli` #106 / #107 / #132 三个
issue 都在追这件事,截至提交时全部 OPEN、官方未回复。

**2. 同一条命令在不同规模的企业行为不同,而且不报错。** 上游维护者在 issue #64 确认:≤10
人「小团队模式」机器人以**授权用户身份**调用、继承其文档权限;>10
人「企业模式」机器人以**独立身份**调用、不继承。后果是同事分享给你的文档,小公司读得到、大公司读同一份返回
`851003`。这不是故障,但不写出来必然被当成故障反复重试。

顺带记入第三条与规模无关的边界:`wecom-cli identity whoami`
返回原文「只能写入或修改机器人创建或拥有的数据」——这是邮件署名固定为「XXX的机器人」、用户对助手所建文档反而没有管理权的根因。

### 条目改动

pointer 条目的 `USAGE.md` 由客户端从内容仓库**按 pinned ref** 抓取(`sync/market.ts` 的
`pointerUsage` ← `code-repo/file-fetcher.ts`),所以只推内容仓库不改 ref
的话客户端看不到。四处一起改,保持 ADR-137 证据链自洽:

| 字段 | 旧 | 新 |
| --- | --- | --- |
| `entry.source.ref` | `665ab1d2` | `047928a` |
| `compliance.reviewedRef` | `665ab1d2` | `047928a` |
| `compliance.reviewedAt` | 2026-09-04 | 2026-09-06 |
| `timestamps.reviewedAt.value` | 2026-09-04 | 2026-09-06 |
| `timestamps.catalogUpdatedAt.value` | 2026-09-04 | 2026-09-06 |

`releasePublishedAt` **不动**——版本仍是 1.0.0,本次只增文档。

已核对:`reviewedRef === source.ref`、`timestamps.reviewedAt ===
compliance.reviewedAt`、`availability: installable`、`license.state:
known`、compliance 五项必填齐全、ref 为 40 位 SHA、`repoUrl` 在官方前缀内。

### 证据等级

| 结论 | 来源 |
| --- | --- |
| `853006` 错误原文与触发条件 | 本机实测复现 |
| 「仅对 ≤10 人企业开放」 | 官方错误码 `853001` 释义 |
| 小团队 / 企业模式身份差异 | 上游 issue #64 维护者确认 |
| 「只能写入机器人拥有的数据」 | `identity whoami` 返回原文 |
| 群聊 7 天限制 | `chat messages list` 的 `begin_time` 字段 schema |

**未核实**:`853006` 的具体判定标准(是否严格按人数、有无灰度名单)与开通路径,官方未公开、上游 issue
未获回复。`USAGE.md` 里已如实标注。


### 追加:一并修正 docs 的 853006 归因

同一 ref 里还带了内容仓库

[`047928a`](047928afe1)
的一处事实修正。原 docs 把 `853006` 写成「机器人未开通『群聊会话』品类」,并给出
「要让它可用:为机器人开通群聊会话品类」——**这是让用户去做一件做不成的事**。

改了 6 处(`04-群聊历史` 四处、`README` / `01-快速开始` / `99-风险与确认` 各处),
只纠正群聊这一处的归因,**不动「能力按品类逐项开通」这条通则**——那条对 `850002`
依然成立。技能侧(`wecom-shared` / `wecom-workflows` / `wecomcli-message`)本就写的是
「企业级不可用」,本次是让 docs 与技能口径一致。

---

## English

The agent detail page's "Usage" section was empty for the WeCom
assistant. The content repo now carries a `USAGE.md`; this PR repins the
listing to it.

It documents two limits that a reader needs **before** installing and
cannot change afterwards:

1. **Chat history is currently limited to corporations of 10 people or
fewer.** Official error `853001` states this; the actual response is
`853006 this tool is not available for your corporation` — the wording
is *corporation*, not *bot*, so asking an admin to enable a bot
capability is a dead end. Reproduced locally; all 12 other service
domains work under the same credential. Upstream issues #106 / #107 /
#132 all remain OPEN with no official response.
2. **The same command behaves differently by corporation size, without
erroring.** Per the upstream maintainer in issue #64, bots in ≤10-person
"small team mode" call **as the authorizing user** and inherit their
document permissions; in ">10 person" enterprise mode they call **under
their own identity** and do not. A doc shared with you is readable in a
small company and returns `851003` in a large one.

A pointer listing's `USAGE.md` is fetched from the content repo **at the
pinned ref**, so `source.ref` and the ref-bound compliance evidence are
updated together to keep the ADR-137 chain self-consistent.
`releasePublishedAt` is unchanged — still 1.0.0, docs only.
2026-09-06 10:11:20 -04:00

DesireCore Market

DesireCore 官方市场仓库,存放官方维护的 Agent/Team/Skill 定义,以及经过整理的第三方 Skill 入口。

Repository Shape

.
├── manifest.json          # Market metadata, supported locales, aggregate stats
├── categories.json        # Category registry and localized labels
├── builtin-skills.json    # Built-in local SKILL.md skills
├── agents/
│   ├── desirecore/
│   │   └── agent.json
│   └── <agent-listing>/
│       ├── agent.json
│       ├── catalog-metadata.v1.json
│       └── USAGE.md            # Optional usage notes (USAGE.<locale>.md for variants)
├── teams/
│   └── <team>/
│       └── entry.json
└── skills/
    ├── <local-skill>/
    │   ├── SKILL.md
    │   └── SKILL.<locale>.md
    └── <external-entry>/
        └── entry.json

The market currently contains:

  • 5 Agents: desirecore, dingtalk-workspace, feishu-orchestrator, invoice-organizer, wecom-assistant
  • 1 Team: contract-review-team
  • 40 local built-in skills with SKILL.md
  • 29 external skill entries with entry.json
  • 69 publishable skills in total (SKILL.md + entry.json)

Skill Sources

Local built-in skills are installable from this repository and must be listed in builtin-skills.json:

baidu-poi-search, ccgp-gov-procurement, clone-agent, cnipa-patent-search, code-intelligence,
configuring-compute, create-agent, creditchina-query, dashscope-image-gen, delete-agent,
dev-environment-setup, discover-agent, docx, frontend-design, guizang-ppt,
image-to-image, mail-operations, manage-skills, manage-teams, markdown,
minimax-music-gen, minimax-video-gen, multi-source-sentiment, nodejs-runtime, pdf, pptx,
presentation-forge, python-runtime, registering-services, s3-storage-operations, skill-creator,
tech-diagram, tianyancha-risk, update-agent, using-services, web-access, workflow, workforce-optimization,
xiaomi-tts, xlsx

builtin-skills.json#retired lists old built-in Skill IDs that clients may safely retire during startup. Clients only remove copies tracked in skills.lock as market/bundled content whose SKILL.md hash still matches the installed record; manually installed or locally modified copies are preserved. An ID must not appear in both skills and retired.

External entries are marketplace pointers to Git/Web/ZIP sources:

agent-reach, ai-news-radar, amap-jsapi-skill, baoyu-skills, dingtalk-api,
dingtalk-cli, flyai-skill, follow-builders, humanizer, humanizer-zh,
ian-xiaohei-illustrations, impeccable, karpathy-guidelines, khazix-skills,
larksuite-cli, last30days, luckin-my-coffee, marketingskills,
mattpocock-skills, minimax-image-gen, minimax-tts, mt-paotui-for-client,
netease-skills, nuwa-skill, taste-skill, watch, watchless,
wechatpay-skills, wecom-cli

Data Formats

Local Skill (skills/<id>/SKILL.md)

Local skills use YAML frontmatter plus Markdown body. The top-level name must equal the directory slug. Display strings live in metadata.i18n.

---
name: web-access
description: >-
  Use this skill when ...
version: 2.0.1
type: procedural
risk_level: low
status: enabled
metadata:
  author: desirecore
  updated_at: '2026-05-05'
  i18n:
    default_locale: en-US
    source_locale: zh-CN
    locales: [zh-CN, en-US]
    zh-CN:
      name: 联网访问
      short_desc: 联网搜索、网页抓取、登录态浏览器访问
      body: ./SKILL.zh-CN.md
      translated_by: human
    en-US:
      name: Web Access
      short_desc: Web search, page fetching, logged-in browser access
      body: ./SKILL.md
      source_hash: sha256:...
      translated_by: human
market:
  category: research
  channel: latest
  maintainer:
    name: DesireCore Official
    verified: true
---

External Entry (skills/<id>/entry.json)

External entries point to upstream packages or repositories. They are counted in manifest.stats.totalSkills but are not included in builtin-skills.json.

{
  "id": "example-skill",
  "name": "Example Skill",
  "category": "development",
  "icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">...</svg>",
  "tags": ["example"],
  "maintainer": {
    "name": "Example",
    "verified": false,
    "account": "example",
    "url": "https://github.com/example/example-skill"
  },
  "stewardship": "community",
  "license": "MIT",
  "redistribution": "allowed",
  "source": {
    "kind": "git",
    "repoUrl": "https://github.com/example/example-skill.git",
    "repoBranch": "main"
  }
}

Team Listing (teams/<id>/entry.json)

A Team is a group of Agents with a supervisor. It is published as a fork pointer only: the team body (team.json, members.json, shared/) always stays in the upstream team repository, and the catalog registers just "what it is and where to fork it from". Installation forks that repository and installs the declared members; updates are a git pull on the fork. Because both actions are Git actions, source.kind must be git and source.repoUrl is required — zip and web cannot express either one — and a Team deliberately has no installPolicy / updatePolicy pair: it is always market-initiated fork plus repository-driven update.

teams/<id>/ therefore holds exactly entry.json plus the sidecar. There is no inline form; a team.json in the catalog is rejected.

{
  "id": "example-team",
  "name": "Example Team",
  "category": "development",
  "tags": ["example"],
  "latestVersion": "0.1.0",
  "maintainer": {
    "name": "Example",
    "verified": false,
    "account": "example",
    "url": "https://github.com/example"
  },
  "stewardship": "community",
  "license": "MIT",
  "redistribution": "source-pointer-only",
  "source": {
    "kind": "git",
    "repoUrl": "https://github.com/example/example-team.git",
    "repoBranch": "main",
    "ref": "0123456789abcdef0123456789abcdef01234567"
  },
  "requiredClientVersion": "10.0.0",
  "avatar": { "t": "示", "bg": "linear-gradient(135deg, #5856D6, #3634A3)" },
  "supervisorName": "Example Supervisor",
  "supervisorAgentId": "example-lead",
  "memberCount": 3,
  "memberNames": ["Example Member One", "Example Member Two"]
}

A Team card is rendered from avatar, not from icon. The client's runtime projection marketTeamSchema requires avatar and has no icon property at all — the same is true of marketAgentSchema, while only marketSkillSchema exposes icon. The entry contract inherits icon from the shared common properties, so it is accepted, but it can never reach a card. The validator therefore requires icon on Skill listings only, and warns when an Agent or Team listing declares one.

redistribution stays source-pointer-only for a Team even under a permissive license: the market never ships the team body, it only points at the repository the client forks. The license governs what a fork may do; redistribution describes how the content is delivered, and for teams that is always "fetch from upstream".

supervisorName, supervisorAgentId, memberCount, memberNames and requiredSkills are display metadata declared by the publisher. They may drift from the upstream repository, so installation, permissions and member resolution must read the forked team.json / members.json instead. Teams are counted in manifest.stats.totalTeams, which the client keeps optional: a catalog with no teams may omit it, and once the key is present it must be exact.

Catalog metadata sidecar (catalog-metadata.v1.json)

The versioned catalog metadata contract is stored at one fixed path next to each legacy item:

agents/<id>/catalog-metadata.v1.json
teams/<id>/catalog-metadata.v1.json
skills/<id>/catalog-metadata.v1.json

Legacy agent.json, SKILL.md, and entry.json files remain the compatibility surface for older clients. New clients merge the sidecar through a deterministic adapter. Any field repeated in both files must have the same value; the validator rejects drift rather than choosing one copy silently.

Agent listings support exactly one of agents/<slug>/agent.json (inline metadata) or agents/<slug>/entry.json (an external pointer), alongside the sidecar. Missing or simultaneous primary files are rejected. For a pointer, entry.id and sidecar identity.id use the catalog directory slug and identity.kind is agent; the upstream AgentFS agent.json.id remains its own UUID and must not be rewritten.

An agent listing may also carry an optional USAGE.md next to agent.json. The client renders it as a separate "Usage" section on the agent detail page, kept apart from fullDesc (which is persona text and also enters the agent's runtime context). Localized variants use USAGE.<locale>.md, resolved through the same fallback chain as the i18n block: requested locale, then i18n.source_locale, then i18n.default_locale, then the unsuffixed file. Its scope is what a reader needs before installing — prerequisites, authorization steps, capability and safety boundaries — not full documentation; clients truncate overlong content. Longer material belongs in a skill's references/ directory, which the agent loads on demand. Listings without the file are unaffected and render no section. Relative image references do not render on the detail page, so keep USAGE.md text-only. See ADR-143 in the DesireCore repository.

Agent pointers first pass the complete raw client contract in schemas/market-agent-entry.client.schema.json, exported from marketAgentEntrySchema in the DesireCore repository at commit 18bbb86f62e1288b1f945209bed74ec72620a9d4. The schema's $comment records the source blob as well. Refresh this generated snapshot from the TypeScript export when changing client compatibility; do not replace it with permissive sidecar validation. Version fields keep their original types and the client's supported format. Installation/update policies must either both be absent (effective market/market) or form a complete supported pair; the sidecar must preserve that effective pair.

Agent pointer latestVersion maps to sidecar release.version; optional requiredClientVersion, installPolicy, and updatePolicy must agree with the sidecar compatibility/spec fields. Pointer source fields must describe the same artifact as provenance.content, and maintainer maps to upstreamMaintainer. An installable Agent pointer must itself pin source.ref (Git) or source.sha256 (Web/ZIP); an immutable ref supplied only by the sidecar cannot pin a mutable entry. Existing immutable-source, license, governance-review and complete-coverage checks still apply. Agent pointers do not receive the built-in Skill exceptions.

Agent 目录必须在 agent.json 内联元数据和 entry.json 外部指针中二选一,并提供 sidecar。 Pointer 原始 JSON 先通过固定客户端提交导出的完整 Schema版本类型与格式、来源路径和策略组合不能由 sidecar 掩盖。 Pointer 的目录 slug、entry.id、sidecar identity.id 必须一致;上游 AgentFS 的 UUID 不改写。 安装/更新策略双缺省时有效值仍是 market/marketsidecar 不得将其改成系统条目。 latestVersion、最低客户端版本和安装/更新策略须与 sidecar 对齐;来源必须是同一个制品。 可安装指针自身必须固定 Git ref 或 Web/ZIP 摘要,不能只在 sidecar 宣称不可变版本。 现有许可、治理审查、不可变来源和完整覆盖门禁继续有效,不适用内置 Skill 的宽松例外。

Team listings are pointer-only, so teams/<slug>/ carries exactly entry.json plus the sidecar; an inline team.json is rejected. Team pointers first pass the complete raw client contract in schemas/market-team-entry.client.schema.json, exported from marketTeamEntrySchema the same way as the Agent snapshot; its $comment records the source commit and blob. entry.id, the directory slug and sidecar identity.id must agree, identity.kind is team, and latestVersion maps to release.version. supervisorName, supervisorAgentId, memberCount, memberNames, requiredSkills and requiredClientVersion are compared symmetrically: the sidecar may neither drop a fact the pointer declares nor invent one it omits, because the client reads the pointer and a version gate that exists only in the sidecar would not gate anything. Pointer source fields must describe the same artifact as provenance.content, and an installable Team pointer must itself pin a full-SHA source.ref — a tag is not a reproducible pin, because a tag can be moved to a different commit after the listing is reviewed.

团队条目只有指针形态:teams/<slug>/ 仅放 entry.json 与 sidecar目录内出现 team.json 直接判非法。 Pointer 原始 JSON 先通过由 marketTeamEntrySchema 导出的完整客户端 Schema source.kind 恒为 git 且必须有 repoUrl,团队没有 installPolicy / updatePolicy 组合。 目录 slug、entry.id、sidecar identity.id 必须一致,identity.kindteam。 展示字段与最低客户端版本双向比对sidecar 既不得丢弃指针声明的事实,也不得凭空补上指针没有的事实。 可安装团队指针自身必须固定完整 SHA 的 source.reftag 或分支不算可复现锁定。

The sidecar records source-owned presentation, release, timestamp, content provenance, governance, compatibility, and type-specific facts. It deliberately cannot declare catalogSourceId, catalog commit/path/trust, effective official status, installation state, device state, health, URLs discovered at runtime, or syncedAt. DesireCore injects trusted catalog provenance and runtime facts.

license.evidencePath, compliance.licenseEvidencePath and compliance.noticePath resolve differently by item shape, because the schema constrains only the string form. Vendored content (built-in Skills, inline Agents) ships inside this repository, so the path is relative to the catalog item directory and the file must actually be there — a missing file is an error. A pointer distributes nothing, so its evidence can only be inside the upstream snapshot at the pinned revision; the validator cannot read that offline, so it warns when such a claim is made against an unpinned pointer. Pin source.ref to a full commit SHA and the claim becomes falsifiable by anyone who fetches it.

Time facts are explicit known/unknown values. A known day uses YYYY-MM-DD with precision: "day"; a known second uses an RFC 3339 UTC value ending in Z with precision: "second". Never use the current date, clone time, or synchronization time to fill an unknown catalog or release timestamp.

Collection children stay in their parent's sidecar. Each child declares the canonical skill + parentId + id identity and its own release fact; a collection parent may have an unknown version, and a child version must not be inferred from the parent.

The strict source schema is schemas/catalog-metadata.v1.schema.json.

Categories

Valid category slugs are declared in categories.json:

productivity, development, business, creative, design, media,
communication, research, data, management

Validation

Run these checks before submitting changes:

# Full market + i18n validation
uv run scripts/i18n/validate-i18n.py

# Catalog sidecar validator unit tests and standalone validation
uv run scripts/catalog/test_validate_catalog_metadata.py
uv run scripts/catalog/test_collection_generator.py
uv run scripts/catalog/validate_catalog_metadata.py

# Translation freshness check
uv run scripts/i18n/translate.py --check

# Verify pinned collection children without changing entry.json (network required;
# mutable collections are reported and skipped because their output is not reproducible)
uv run scripts/gen-collection-children.py --check

# Optional network check for entry.json source URLs
uv run scripts/i18n/validate-i18n.py --online

The validators check market stats, category references, builtin-skills.json, entry.json structure, sidecar schema and legacy consistency, immutable source evidence, collection identity, i18n completeness, and translation freshness. Human-locked translations (translated_by: human) must keep source_hash aligned after manual review. During a data migration, scripts/catalog/validate_catalog_metadata.py --require-complete additionally requires one sidecar for every top-level Agent, Team and Skill.

Detailed i18n guidance is in docs/I18N.md.

License

MIT License. See LICENSE.

Description
DesireCore 官方市场仓库。
Readme MIT 22 MiB
Languages
Python 85%
HTML 13.3%
Shell 0.9%
JavaScript 0.6%
PowerShell 0.2%