From 5f7c48b7a4b8ce85ed94857f7e6970faed6df958 Mon Sep 17 00:00:00 2001 From: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:25:27 +0800 Subject: [PATCH] feat(bootstrap): publish starter skills in runtime manifest Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> --- builtin-skills/README.md | 3 + docs/21-official-starter-skills-plan.md | 2 +- docs/22-builtin-skills-candidate-pool.md | 5 +- scripts/tests/build-builtin-skills-test.sh | 28 ++++++ .../resources/builtin-skills/manifest.json | 90 +++++++++++++++++++ .../BuiltinSkillManifestLoaderTest.java | 2 +- 6 files changed, 125 insertions(+), 5 deletions(-) diff --git a/builtin-skills/README.md b/builtin-skills/README.md index 31302b4c..83376611 100644 --- a/builtin-skills/README.md +++ b/builtin-skills/README.md @@ -25,6 +25,9 @@ added to the runtime manifest only after its immutable CDN URL is available; the the matching SHA-256 so the backend can reject changed or incorrectly uploaded bytes before extraction. +The first batch of 15 packages is pinned in the runtime manifest. A clean deployment initializes +these packages alongside the existing built-in Skills in the public `@global` namespace. + ## Share a Skill with the Community A Skill shared with the community may be considered for the curated starter collection. diff --git a/docs/21-official-starter-skills-plan.md b/docs/21-official-starter-skills-plan.md index 9d03e346..29251930 100644 --- a/docs/21-official-starter-skills-plan.md +++ b/docs/21-official-starter-skills-plan.md @@ -122,7 +122,7 @@ Catalog 按单个 Skill 的许可证筛选。Anthropic 的 `docx`、`pdf`、`ppt - 跑通批量检查、打包、上传和 manifest 更新流程。 - 已从 70 个候选中选定 A05、A07–A15、B06、B07、B10、B11、B24,共 15 个。 - 15 个候选均已完成必要适配、来源与许可证登记、生产包校验和静态安全复测。 -- 待完成不可变制品上传、manifest 哈希登记和干净实例同步验证。 +- 已完成不可变制品上传和 manifest 哈希登记,待完成干净实例同步验证。 - 不要求第一批为了形式上覆盖全部类别而降低门槛;旅行规划等缺少合格候选的场景留到第二批。 ### 第二批:扩充到 30 个 diff --git a/docs/22-builtin-skills-candidate-pool.md b/docs/22-builtin-skills-candidate-pool.md index 9be85d60..e818fa4d 100644 --- a/docs/22-builtin-skills-candidate-pool.md +++ b/docs/22-builtin-skills-candidate-pool.md @@ -209,6 +209,5 @@ B25 的核心行程生成实测失败,并会把敏感旅行画像写入宿主 7. 将不可变 URL 和制品 SHA-256 写入 `server/skillhub-app/src/main/resources/builtin-skills/manifest.json`,在干净部署中验证同步、下载和安装。 -第一批 15 个适配包已经完成内容、安全和确定性构建检查;在官方不可变 CDN URL 可用前,暂不把 -它们写入运行时 manifest。把 GitHub 分支下载地址直接写进 manifest,会导致内容变化后无法审计 -和复现。 +第一批 15 个适配包已经完成内容、安全和确定性构建检查,并已通过官方不可变 CDN URL 和 +SHA-256 写入运行时 manifest。后续更新必须发布新版本和新制品,不得覆盖当前 URL 对应的字节。 diff --git a/scripts/tests/build-builtin-skills-test.sh b/scripts/tests/build-builtin-skills-test.sh index 8a63f9d6..ba9f7c82 100755 --- a/scripts/tests/build-builtin-skills-test.sh +++ b/scripts/tests/build-builtin-skills-test.sh @@ -18,6 +18,34 @@ python3 "$BUILDER" --output "$second" cmp "$first/artifacts.json" "$second/artifacts.json" +runtime_manifest="$REPO_ROOT/server/skillhub-app/src/main/resources/builtin-skills/manifest.json" +python3 - "$first/artifacts.json" "$runtime_manifest" <<'PY' +import json +import sys +from pathlib import Path +from urllib.parse import urlsplit + +artifacts = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))["artifacts"] +runtime_items = json.loads(Path(sys.argv[2]).read_text(encoding="utf-8"))["skills"] +runtime_by_coordinate = {} +for item in runtime_items: + coordinate = (item["slug"], item["version"]) + assert coordinate not in runtime_by_coordinate, coordinate + runtime_by_coordinate[coordinate] = item + +assert len(runtime_items) == 17, len(runtime_items) +for artifact in artifacts: + coordinate = (artifact["slug"], artifact["version"]) + assert coordinate in runtime_by_coordinate, coordinate + runtime_item = runtime_by_coordinate[coordinate] + assert runtime_item["sha256"] == artifact["sha256"], coordinate + parsed_url = urlsplit(runtime_item["url"]) + assert parsed_url.scheme == "https", coordinate + assert parsed_url.hostname == "bjcdn.openstorage.cn", coordinate + assert not parsed_url.query and not parsed_url.fragment, coordinate + assert parsed_url.path.endswith(f'/{artifact["sha256"]}.zip'), coordinate +PY + python3 - "$first" <<'PY' import json import sys diff --git a/server/skillhub-app/src/main/resources/builtin-skills/manifest.json b/server/skillhub-app/src/main/resources/builtin-skills/manifest.json index 24ea0a81..ac6a5765 100644 --- a/server/skillhub-app/src/main/resources/builtin-skills/manifest.json +++ b/server/skillhub-app/src/main/resources/builtin-skills/manifest.json @@ -11,6 +11,96 @@ "version": "1.1", "url": "https://bjcdn.openstorage.cn/aicontest/2026-06-12/9d063bc7-223a-4762-adeb-305c268aa29e.zip", "sha256": "77b16d62c1adaf8c1d5ca06b9bff26005bc77da345e6036cc5f1f91bdee1a149" + }, + { + "slug": "ai-claim-checker", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/9d8a9ef1-6c63-483a-a54d-b593180572a2/skillhub-builtin-skills/ai-claim-checker/1.0.0/19fd699fc5e67469bb764d5f695894c1a39e49055060152aa6168629ca0f0ea5.zip", + "sha256": "19fd699fc5e67469bb764d5f695894c1a39e49055060152aa6168629ca0f0ea5" + }, + { + "slug": "daily-standup-journal", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/c6dc807b-5255-4aa9-8bdd-a708b9d159a6/skillhub-builtin-skills/daily-standup-journal/1.0.0/fd365dd3e1a4302044839bf3317c262c4bad650e0a677b7a1ca1d1ad5b8ab1bd.zip", + "sha256": "fd365dd3e1a4302044839bf3317c262c4bad650e0a677b7a1ca1d1ad5b8ab1bd" + }, + { + "slug": "decision-matrix", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/73347ade-b71d-42e0-ad14-a63ac761d7ab/skillhub-builtin-skills/decision-matrix/1.0.0/1f284d78ebd8530b10d11a801237c11a0b24a08fe1798587df99ade7686b827a.zip", + "sha256": "1f284d78ebd8530b10d11a801237c11a0b24a08fe1798587df99ade7686b827a" + }, + { + "slug": "diagram-maker", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/3d36219f-d700-4623-b482-39a39691ec22/skillhub-builtin-skills/diagram-maker/1.0.0/4c2fd87851f7a2a6dfca712887f8135f1696e23e8dc24cbb48f82303029eed17.zip", + "sha256": "4c2fd87851f7a2a6dfca712887f8135f1696e23e8dc24cbb48f82303029eed17" + }, + { + "slug": "documentation-writer", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/e7e7b3ce-4923-4528-b7b4-e89de10802fa/skillhub-builtin-skills/documentation-writer/1.0.0/6a2cff6c0248c9a01c2475f2467606f06312ffc093c4ac0637ad50ba13b421aa.zip", + "sha256": "6a2cff6c0248c9a01c2475f2467606f06312ffc093c4ac0637ad50ba13b421aa" + }, + { + "slug": "exam-ready", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/2a4ff8f9-7f57-435f-8eb1-69fe33afa99e/skillhub-builtin-skills/exam-ready/1.0.0/aea81a497157a19e4b136f2cfe3ba0764ebb52e520e4a87fa0446e5465f97663.zip", + "sha256": "aea81a497157a19e4b136f2cfe3ba0764ebb52e520e4a87fa0446e5465f97663" + }, + { + "slug": "frontend-design", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/fae63ded-f222-4583-a723-d6d9529360e0/skillhub-builtin-skills/frontend-design/1.0.0/67b2f34163874e56ba43a0a9ed3d1012d752615a1a80f0c26608a702d9fe394e.zip", + "sha256": "67b2f34163874e56ba43a0a9ed3d1012d752615a1a80f0c26608a702d9fe394e" + }, + { + "slug": "linkedin-post-formatter", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/4e19c89f-7fa2-44fa-a3bf-90ec959258c0/skillhub-builtin-skills/linkedin-post-formatter/1.0.0/171acf2d0574265b1ececa53759658aeb582aae4c859d4199b1ff322d65f8642.zip", + "sha256": "171acf2d0574265b1ececa53759658aeb582aae4c859d4199b1ff322d65f8642" + }, + { + "slug": "meeting-note-summarizer", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/6cf347a7-ccc5-4016-b4ca-6263959a1b08/skillhub-builtin-skills/meeting-note-summarizer/1.0.0/5add401203f323bc1cbb350f306d3a5d3f3b16c2ad6578e7cab55d2c196152ca.zip", + "sha256": "5add401203f323bc1cbb350f306d3a5d3f3b16c2ad6578e7cab55d2c196152ca" + }, + { + "slug": "retrieval-practice-generator", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/ac9086e8-ee32-4baa-bf42-0bc3f5c59558/skillhub-builtin-skills/retrieval-practice-generator/1.0.0/8e1b21f9c02312378da4d5493297d98a2ce40ba03f83a51e24c97ad53f144dc1.zip", + "sha256": "8e1b21f9c02312378da4d5493297d98a2ce40ba03f83a51e24c97ad53f144dc1" + }, + { + "slug": "storytelling-advisor", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/12e1eaea-cffc-4d67-b452-5383868475d2/skillhub-builtin-skills/storytelling-advisor/1.0.0/c44427e0a45e3a63dc47fb2a58e9b40f9db7a6d29715fc38a2d6162e89cd4be3.zip", + "sha256": "c44427e0a45e3a63dc47fb2a58e9b40f9db7a6d29715fc38a2d6162e89cd4be3" + }, + { + "slug": "study-strategy-selector", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/ac7017cf-7d83-46e0-a467-7e2d199cbd03/skillhub-builtin-skills/study-strategy-selector/1.0.0/ea5ef41b449b823cd996be18c4f6af2d9944a0571aa7c65091327cc1893657f1.zip", + "sha256": "ea5ef41b449b823cd996be18c4f6af2d9944a0571aa7c65091327cc1893657f1" + }, + { + "slug": "time-blocking-scheduler", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/9b032189-7bba-407e-adb2-bcda2c0c2765/skillhub-builtin-skills/time-blocking-scheduler/1.0.0/005b0d9afda5bb8f4dd8b8d43b2201e26f2f2792a1d7b57dc7667367d543e76e.zip", + "sha256": "005b0d9afda5bb8f4dd8b8d43b2201e26f2f2792a1d7b57dc7667367d543e76e" + }, + { + "slug": "video-frames", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/4136bddd-868a-44e3-a16e-16321433733c/skillhub-builtin-skills/video-frames/1.0.0/7b4e9f1fb30b5f8318b061e1c5aeda0249d73746acc548ee4d7ff13b3d999966.zip", + "sha256": "7b4e9f1fb30b5f8318b061e1c5aeda0249d73746acc548ee4d7ff13b3d999966" + }, + { + "slug": "weather", + "version": "1.0.0", + "url": "https://bjcdn.openstorage.cn/open_res/xfyundoc/2026-07-31/0170ce8f-ad41-4819-bc50-9b572b1c6510/skillhub-builtin-skills/weather/1.0.0/181e36c0fd6ca5f6cdf224276dd12e0fd203f83456a988a6bcf15cc4f3c20dd6.zip", + "sha256": "181e36c0fd6ca5f6cdf224276dd12e0fd203f83456a988a6bcf15cc4f3c20dd6" } ] } diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/bootstrap/BuiltinSkillManifestLoaderTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/bootstrap/BuiltinSkillManifestLoaderTest.java index 71229f07..58ed6419 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/bootstrap/BuiltinSkillManifestLoaderTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/bootstrap/BuiltinSkillManifestLoaderTest.java @@ -56,7 +56,7 @@ class BuiltinSkillManifestLoaderTest { List items = loader.load(); - assertThat(items).isNotEmpty(); + assertThat(items).hasSize(17); assertThat(items).allSatisfy(item -> assertThat(item.sha256()).matches("[0-9a-f]{64}") );