diff --git a/README.md b/README.md index a59aa77..4802f30 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,24 @@ themes/ 主题资产(用户复制到 ~/.dsh-tui/themes/) [插件开发指南](https://github.com/ccch1mneyyy/dsh-TUI/blob/main/docs/plugins.md) (Full seam catalogue, red lines, and listing: the core repo's [Plugin development guide](https://github.com/ccch1mneyyy/dsh-TUI/blob/main/docs/plugins.en.md)) + +## 生态规范与验证(dsh-ecosystem-spec v0.15) + +本模板随 [dsh-ecosystem-spec](https://github.com/T-Auto/dsh-ecosystem-spec) +(社区 v0.15 准入 profile)附上声明性身份文件 `dsh-plugin.json`:用 `facets.host` +(entry `lib/types/index.js` + `apiVersion v1alpha1`)、`requires.contracts` +(`messages.dsh/v1alpha1#MessageObserver`)、`permissions` +(`messages.observe.read`,默认 deny)与 `subscriptions` 描述插件的 v0.15 身份 +与契约面;实际可运行层仍是 `package.json` 的 `dsh.bundle.patch` + +`cordis.patch.yml`(见 `overrides`)。 + +验证(需要一个 [dsh-ecosystem-spec](https://github.com/T-Auto/dsh-ecosystem-spec) +检出,可用 `DASH_ECOSYSTEM_SPEC` 指向;检出内先 `npm run test:standalone`): + +```sh +npm run verify:plugin +``` + +预期决策为 `waiting_authorization`(`messages.observe.read` 默认 deny,符合 +RFC 0005 默认拒绝语义);授权后(`~/.dsh-tui/extension-grants.json`)为 +`compatible`。 diff --git a/dsh-plugin.json b/dsh-plugin.json new file mode 100644 index 0000000..ccc3f9d --- /dev/null +++ b/dsh-plugin.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://dsh.community/schemas/dsh-plugin-0.15.json", + "id": "com.dsh-tui-ecosystem.example-plugin", + "name": "dsh-tui example plugin", + "version": "0.1.0", + "manifestVersion": "0.15", + "facets": { + "host": { + "entry": "lib/types/index.js", + "apiVersion": "v1alpha1" + } + }, + "requires": { + "contracts": [ + { + "apiVersion": "messages.dsh/v1alpha1", + "kind": "MessageObserver" + } + ] + }, + "permissions": [ + { + "name": "messages.observe.read", + "scope": "com.dsh-tui-ecosystem.example-plugin", + "reason": "订阅会话事件以统计每会话 turn 数(默认 deny,授权后才能观察)" + } + ], + "contributes": { + "commands": [] + }, + "subscriptions": [ + "messages.observe" + ], + "license": "MIT", + "source": { + "repository": "https://github.com/dsh-tui-ecosystem/plugin-template", + "revision": "main" + }, + "overrides": [ + { + "target": "cordis.patch.yml", + "kind": "patch", + "description": "实际可运行层仍是 Cordis bundle(见 package.json 的 dsh.bundle.patch);本 manifest 是 v0.15 身份 / 契约声明层,两者暂未统一。" + } + ] +} diff --git a/package.json b/package.json index dcecbd4..d007565 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "node": "^22.19 || >=24" }, "scripts": { - "build": "tsc -p tsconfig.json" + "build": "tsc -p tsconfig.json", + "verify:plugin": "node scripts/verify-plugin.mjs" }, "license": "MIT", "dsh": { diff --git a/scripts/verify-plugin.mjs b/scripts/verify-plugin.mjs new file mode 100644 index 0000000..b79aa7f --- /dev/null +++ b/scripts/verify-plugin.mjs @@ -0,0 +1,30 @@ +#!/usr/bin/env node +/** + * 用 dsh-ecosystem-spec 的 conformance 校验本模板的 `dsh-plugin.json`。 + * + * 用法: + * 1) 把 https://github.com/T-Auto/dsh-ecosystem-spec 克隆到本仓库同级 + * (或设置 DASH_ECOSYSTEM_SPEC 指向它的检出路径); + * 2) 在 spec 检出里先跑 `npm run test:standalone` 构建依赖; + * 3) 回到本仓库执行 `npm run verify:plugin`。 + * + * 预期结果:`waiting_authorization` —— 本模板声明 `messages.observe.read` + * (权限默认 deny),这正是默认拒绝的正确语义;在该会话授权 + * (`~/.dsh-tui/extension-grants.json`)后应为 `compatible`。 + */ +import { spawnSync } from 'node:child_process' +import { existsSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' + +const here = dirname(fileURLToPath(import.meta.url)) +const spec = process.env.DASH_ECOSYSTEM_SPEC ?? join(here, '..', '..', 'dsh-ecosystem-spec') +if (!existsSync(join(spec, 'package.json'))) { + console.error('[verify:plugin] 未找到 dsh-ecosystem-spec。请先克隆到本仓库同级(或设 DASH_ECOSYSTEM_SPEC 指向它),并在其内运行 npm run test:standalone 构建依赖。') + process.exit(2) +} +const manifest = resolve(here, '..', 'dsh-plugin.json') +const run = spawnSync(process.execPath, [join(spec, 'scripts', 'validate-manifest.mjs'), '--manifest', manifest], { stdio: 'inherit' }) +console.log(`[verify:plugin] validate-manifest exit=${run.status}`) +console.log('[verify:plugin] 说明:模板声明 messages.observe.read(默认 deny),预期决策为 waiting_authorization;授权后为 compatible。') +process.exit(run.status ?? 1)