@shgroup/dsh-serenity-hooks 1.54.0 → 1.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,7 +76,7 @@ dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
76
76
  | `msm` | 小工具执行入口:`msm("名字", ["参数"])`;名字记不全就给候选;`inspect=true` 看用法 | 调用工作区里注册的任何小工具 |
77
77
  | `praxis` | 按需给 AI 注入四套"做事方法":输出自检(eap)、设计对齐(neat)、认知连续性(cce)、本体工程(ontology) | 要它把话说清楚 / 先对齐再动手 / 动手前先把领域结构显式化时 |
78
78
  | `ontology` | 本体工程**引擎**(能跑的那个):读 `.ttl` 本体文件,做结构校验(M1–M10,含公理表达式语法)、生成摘要、查声明与实况是否一致(V1–V4)、出语义审查提示词、出"公理 ↔ 技能"合规清单;还能写一份新本体的模板 | 想给某个领域建/校验本体时。⚠️ 与 `praxis ontology` 是**同一领域的两个面**:那个是**方法文本**(怎么建模),这个是**引擎**(真去检查)。路径必须在工作区内 |
79
- | `serenity-skill-creator` | 增强型 skill 标准(**serenity-skill**)的 **creator**:`guide`(编写与优化方法,先读它)/`create`(生成 skill 骨架 = SKILL.md + skill.ttl + references/,**基础链的相对路径由它算**)/`check`(**A1 结构 + A2 链上基础链**,三态可分辨:已建模通过/普通 skill/建模了但检查没跑成)/`review`(**C 档**:文字与本体逐条的合规问题清单,半机械,要人回答)/`index`(预览**模型实际会看到**的第二层参考件清单)/`status`(全容器一览:哪些已建模) | 新建或改造 skill、给 skill 建本体、想知道"模型到底看不看得见我那些参考件"时 |
79
+ | `serenity-skill-creator` | 增强型 skill 标准(**serenity-skill**)的 **creator**:`guide`(编写与优化方法,先读它)/`create`(生成 skill 骨架 = SKILL.md + skill.ttl + references/,**基础链的相对路径由它算**)/`check`(**A3 分层档**(**每个 skill 都查**:顶层非桩 / 顶层不自述"只是导航层" / references/ 一级 .md 全部被点名)+ **A1 结构 + A2 链上基础链**,三态可分辨:已建模通过/普通 skill/建模了但检查没跑成)/`review`(**C 档**:文字与本体逐条的合规问题清单,半机械,要人回答)/`index`(预览**模型实际会看到**的第二层参考件清单)/`status`(全容器一览:哪些已建模) | 新建或改造 skill、给 skill 建本体、想知道"模型到底看不看得见我那些参考件"时 |
80
80
  | `handyman` | 杂工:派一个便宜模型的助手干活。**默认模式(foreground)**= 一次串行委派、拿回结果;**background 模式**= 循环干活直到完成(完成码校验 / 轮次上限 / 自动重启 / 进度文件),也可一次派多个并行 | 大批量、重复性的活(扫描几十个技能、逐用例回归) |
81
81
  | `localstore` | 存密钥和配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git |
82
82
  | `container_admin` | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具、改配置时 |
@@ -158,6 +158,10 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
158
158
  └── files_from_user/
159
159
  ```
160
160
 
161
+ > 🔴 **技能的两层披露**:技能目录里除了 `SKILL.md`,还可以有 `references/`(参考件)与 `skill.ttl`(该技能的本体约束)。
162
+ > 助手看到的是**两层**:**目录那一行就带参考件文件名**(插件按文件树即时生成 ⇒ 你新增一个文件它自己就更新,**不用手写**),
163
+ > 真要用时它才去 `read` 打开正文 —— **正文不进上下文,除非它自己去取**。
164
+
161
165
  ---
162
166
 
163
167
  ## 5. 能拿它做什么(12 个真实用例)
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.54.0",
3
+ "version": "1.56.0",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/handyman/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1(deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
package/lib/index.js CHANGED
@@ -2246,6 +2246,16 @@ function truncateContent(content, maxChars) {
2246
2246
  * `references/*-domain.ttl`(旧名)一律当**普通参考件**:不特殊对待、不告警 —— 那 14 份由 CCC 自行改名。
2247
2247
  * 🔴 「未建模」不是异常(裁决 Q6 / 判据 J9):无 `skill.ttl` 的**普通 skill** 照常产出索引,
2248
2248
  * **零告警、零误差** —— 增强必须对普通 skill 完全向后兼容。
2249
+ *
2250
+ * 🔴 **两个面,两个入口**(2026-10-12 增;owner 裁决 O2)—— 同源、但成本形态不同:
2251
+ * · **载入面** `buildResourceIndex()` —— 完整索引(名字 + 首标题 + 字节),带 `.md` 文件头读取;
2252
+ * 在三条路径上各附一次:入口段(`system-prompt.ts` order −50)/轨迹段(`trajectory-skills.ts`
2253
+ * order −45)/目录 provider 的 `get()`(`opencode-skills.ts`)。
2254
+ * · **目录面** `buildResourceNameSuffix()` —— **只有名字**,**不读任何正文**;只挂一处:
2255
+ * 目录 provider 的 `list()`(`available_skills` 的 `SkillSummary.description`)。
2256
+ * 🔴 为什么目录面在这里:`SkillSummary` 契约里**没有列资源的位**(只有 name/description/whenToUse)
2257
+ * ⇒ `description` 是唯一位置,且必须**自动生成**。
2258
+ * ⇒ 两个面**共用** `collectEntries()`(范围 = 规则⑥只写一遍)。
2249
2259
  */
2250
2260
  /** 第二层占位口:本 skill 的本体约束文件(固定名,设计 §5.1) */
2251
2261
  const SKILL_ONTOLOGY_FILE = "skill.ttl";
@@ -2308,7 +2318,8 @@ function scanDirStats(dir) {
2308
2318
  capped
2309
2319
  };
2310
2320
  }
2311
- /** 按 UTF-8 **字节序**比较两个相对路径(规则②;不是 locale 比较、不是 mtime) */
2321
+ /** 按 UTF-8 **字节序**比较两个相对路径(规则②;不是 locale 比较、不是 mtime)。
2322
+ * 参数放宽到 `{ key }`:**未加水**的条目与**已加水**的条目共用同一个比较器 ⇒ 排序规则只写一遍。 */
2312
2323
  function byByteOrder(a, b) {
2313
2324
  return Buffer.compare(a.key, b.key);
2314
2325
  }
@@ -2354,25 +2365,15 @@ function firstHeading(file) {
2354
2365
  }
2355
2366
  return "";
2356
2367
  }
2357
- /** 收集候选(`references/` 一级条目 + 固定名本体),并按字节序排好 */
2358
- function collectItems(skillDir) {
2359
- const items = [];
2360
- const add = (rel, abs, ontology) => {
2361
- let bytes;
2362
- try {
2363
- bytes = statSync(abs).size;
2364
- } catch {
2365
- return;
2366
- }
2367
- items.push({
2368
- rel,
2369
- kind: "file",
2370
- bytes,
2371
- excerpt: rel.endsWith(".md") ? firstHeading(abs) : "",
2372
- ontology,
2373
- key: Buffer.from(rel, "utf-8")
2374
- });
2375
- };
2368
+ /**
2369
+ * 收集第二层的**条目**(范围 = 规则⑥:`references/` 一级条目 + 固定名本体)。
2370
+ *
2371
+ * 🔴 **只做 `readdir` / `stat`,不读任何文件正文** —— 两个消费者(第二层索引 / 目录面的名字清单)
2372
+ * **共用这一份范围定义**:规则⑥只该有一个家,各写一遍必然漂移。
2373
+ * 🔴 返回已按**字节序**排好(规则②:确定性,不用 mtime)。
2374
+ */
2375
+ function collectEntries(skillDir) {
2376
+ const entries = [];
2376
2377
  const refDir = join(skillDir, REFERENCE_DIR);
2377
2378
  if (existsSync(refDir)) {
2378
2379
  let names = [];
@@ -2390,24 +2391,64 @@ function collectItems(skillDir) {
2390
2391
  continue;
2391
2392
  }
2392
2393
  const rel = `${REFERENCE_DIR}/${name}`;
2393
- if (isDir) {
2394
- const { files, bytes, capped } = scanDirStats(abs);
2395
- items.push({
2396
- rel,
2397
- kind: "dir",
2398
- bytes,
2399
- excerpt: `子目录 · ${capped ? `≥${groupThousands(files)}` : groupThousands(files)} 个文件`,
2400
- ontology: false,
2401
- key: Buffer.from(rel, "utf-8")
2402
- });
2403
- continue;
2404
- }
2405
- add(rel, abs, false);
2394
+ entries.push({
2395
+ rel,
2396
+ kind: isDir ? "dir" : "file",
2397
+ abs,
2398
+ ontology: false,
2399
+ key: Buffer.from(rel, "utf-8")
2400
+ });
2406
2401
  }
2407
2402
  }
2408
2403
  const ontoAbs = join(skillDir, SKILL_ONTOLOGY_FILE);
2409
- if (existsSync(ontoAbs)) add(SKILL_ONTOLOGY_FILE, ontoAbs, true);
2410
- items.sort(byByteOrder);
2404
+ if (existsSync(ontoAbs)) entries.push({
2405
+ rel: SKILL_ONTOLOGY_FILE,
2406
+ kind: "file",
2407
+ abs: ontoAbs,
2408
+ ontology: true,
2409
+ key: Buffer.from(SKILL_ONTOLOGY_FILE, "utf-8")
2410
+ });
2411
+ entries.sort(byByteOrder);
2412
+ return entries;
2413
+ }
2414
+ /**
2415
+ * 给条目**加水**(字节 + 摘要)—— 这两项都要读盘,因此与"有哪些条目"分开。
2416
+ * 读不到 ⇒ `null`(宁可少列,也不列出读不到的项)。
2417
+ */
2418
+ function hydrate(entry) {
2419
+ if (entry.kind === "dir") {
2420
+ const { files, bytes, capped } = scanDirStats(entry.abs);
2421
+ return {
2422
+ rel: entry.rel,
2423
+ kind: "dir",
2424
+ bytes,
2425
+ excerpt: `子目录 · ${capped ? `≥${groupThousands(files)}` : groupThousands(files)} 个文件`,
2426
+ ontology: false,
2427
+ key: entry.key
2428
+ };
2429
+ }
2430
+ let bytes;
2431
+ try {
2432
+ bytes = statSync(entry.abs).size;
2433
+ } catch {
2434
+ return null;
2435
+ }
2436
+ return {
2437
+ rel: entry.rel,
2438
+ kind: "file",
2439
+ bytes,
2440
+ excerpt: entry.rel.endsWith(".md") ? firstHeading(entry.abs) : "",
2441
+ ontology: entry.ontology,
2442
+ key: entry.key
2443
+ };
2444
+ }
2445
+ /** 收集候选(`references/` 一级条目 + 固定名本体),加好水并按字节序排好 */
2446
+ function collectItems(skillDir) {
2447
+ const items = [];
2448
+ for (const entry of collectEntries(skillDir)) {
2449
+ const item = hydrate(entry);
2450
+ if (item !== null) items.push(item);
2451
+ }
2411
2452
  return items;
2412
2453
  }
2413
2454
  /**
@@ -2439,6 +2480,35 @@ function buildResourceIndex(skillDir, options = {}) {
2439
2480
  if (body.length <= maxChars) return body;
2440
2481
  return `${body.slice(0, maxChars)}\n…(第二层索引已按 ${groupThousands(maxChars)} 字符上限截断,原文 ${groupThousands(body.length)} 字符)`;
2441
2482
  }
2483
+ /**
2484
+ * 收集**只有名字**的第二层清单(目录面专用)。
2485
+ *
2486
+ * 为什么单独一个入口(而不是复用 `buildResourceIndex`):**成本形态不同** ——
2487
+ * 索引要给每个 `.md` 读文件头取摘要(规则④),而目录面是**每请求 × 每个 skill** 都要算的
2488
+ * ⇒ 这条路径**一个字节正文都不读**(只 `readdir`/`stat`)。
2489
+ * 范围仍与索引**同源**(共用 `collectEntries` ⇒ 规则⑥只有一个家)。
2490
+ */
2491
+ function buildResourceNames(skillDir, options = {}) {
2492
+ const maxItems = options.maxItems ?? 40;
2493
+ const entries = collectEntries(skillDir);
2494
+ const shown = entries.slice(0, maxItems);
2495
+ return {
2496
+ names: shown.map((e) => e.kind === "dir" ? `${basename(e.rel)}/` : basename(e.rel)),
2497
+ hidden: entries.length - shown.length
2498
+ };
2499
+ }
2500
+ /**
2501
+ * 目录面后缀:把名字清单拼成**可直接接在 `description` 后面**的一段文本。
2502
+ *
2503
+ * 🔴 **自动生成,绝不手写**(手写必与文件树漂);无可列项 ⇒ `''`(**普通 skill 零噪声** —— 判据 J9)。
2504
+ * 🔴 **有界 + 响亮**(规则③):超上限时写出"另有 N 项",**绝不静默截断**。
2505
+ */
2506
+ function buildResourceNameSuffix(skillDir, options = {}) {
2507
+ const { names, hidden } = buildResourceNames(skillDir, options);
2508
+ if (names.length === 0) return "";
2509
+ const tail = hidden > 0 ? ` …另有 ${hidden} 项` : "";
2510
+ return `(参考件:${names.join(" / ")}${tail})`;
2511
+ }
2442
2512
  //#endregion
2443
2513
  //#region src/trajectory-skills.ts
2444
2514
  /**
@@ -7719,6 +7789,123 @@ function createOntologyTool() {
7719
7789
  });
7720
7790
  }
7721
7791
  //#endregion
7792
+ //#region src/skills/skill-layering.ts
7793
+ /**
7794
+ * skill-layering.ts(库层,零 DSH 依赖)— **EAP 分层抽象树档(A3)的机械判据**
7795
+ *
7796
+ * 缘起(owner 2026-10-12 令「**根据本次经验完善 serenity-skill-creator;确保未来创建和改进 skill
7797
+ * 都保持 EAP 分层抽象树结构**」):本轮 dsp 开发 skill 的切片**把树倒置了** —— SKILL.md 被切成
7798
+ * 3.4 KB 的**导航层**(只指向下、不说顶层的话),而顶层该说的"身份/模型/约束"全沉到了 references/。
7799
+ * 那次事故的**形状是机械可查的**,所以把它固化成判据,而不是只写进方法正文(D119 同族:
7800
+ * 「写进文档的规则」不会拦住下一次,**能跑起来的判据才会**)。
7801
+ *
7802
+ * 🔴 **本档与 A1/A2 的分工**:
7803
+ * · A3 判的是**文字住在哪一层**(结构形态)—— **每个 skill 都适用**,与有没有 `skill.ttl` 无关。
7804
+ * · A1/A2 判的是**本体**(结构合法性 + 链上基础链)—— 只有已建模的 skill 适用(J9:未建模不是异常)。
7805
+ *
7806
+ * 🔴 **只报不改**:本档给的是判据与可行动修法;改写 SKILL.md 是作者/模型的活(语义判断不在机械档)。
7807
+ * 🔴 **不重写别人的规则**:references 参考件的**首标题**规则归 `resource-index.ts`(`firstHeading`),
7808
+ * 这里只做"列出 references/ 下一级 .md"这一件事。
7809
+ *
7810
+ * ⚠️ **编号消歧(必读)**:本档叫 **A3**,但**与 v1.54.0 记录里那个"已下线的 A3(引用可兑现)"
7811
+ * 不是同一档** —— 那一条是照引擎源码"意图"推断的,实测打假后**决定不写第二实现**。
7812
+ * 本条是 2026-10-12 **新立**的**分层形态**档(判"文字住在哪一层"),与"引用可兑现"无关。
7813
+ */
7814
+ /** 顶层正文(去掉 frontmatter 与生成的导航块)的**下限**:低于它 = 顶层只是桩 */
7815
+ const TOP_LAYER_MIN_BYTES = 2048;
7816
+ /** 生成块(第二层清单)的哨兵 —— 它由 `skill-lint split` / 生成器产出,**不算顶层正文** */
7817
+ const NAV_BLOCK_BEGIN = "<!-- skill-lint:split-nav -->";
7818
+ const NAV_BLOCK_END = "<!-- /skill-lint:split-nav -->";
7819
+ /**
7820
+ * "本文件只是导航层"这类**自述** —— 它是树倒置的**直接症状**(顶层自己声明什么都不说)。
7821
+ * 正常 skill 不会写这句话 ⇒ 这条判据**几乎不会假阳**。
7822
+ */
7823
+ const NAV_SELF_DESCRIPTION = /(?:只是|仅作|仅仅是|只留|只剩|纯)(?:一个)?导航(?:层|文件|块)|导航(?:层|块)(?:而已|罢了)/;
7824
+ /** 去掉 YAML frontmatter(`---` 包起来的那段) */
7825
+ function stripFrontmatter(text) {
7826
+ if (!text.startsWith("---")) return text;
7827
+ const end = text.indexOf("\n---", 3);
7828
+ if (end === -1) return text;
7829
+ const after = text.indexOf("\n", end + 1);
7830
+ return after === -1 ? "" : text.slice(after + 1);
7831
+ }
7832
+ /** 扣掉生成块;返回 [剩下的正文, 被扣掉的字节数] */
7833
+ function stripNavBlock(text) {
7834
+ const begin = text.indexOf(NAV_BLOCK_BEGIN);
7835
+ if (begin === -1) return [text, 0];
7836
+ const end = text.indexOf(NAV_BLOCK_END, begin);
7837
+ if (end === -1) return [text, 0];
7838
+ const cut = text.slice(begin, end + 30);
7839
+ return [text.slice(0, begin) + text.slice(end + 30), Buffer.byteLength(cut, "utf-8")];
7840
+ }
7841
+ /** references/ **一级**下的 .md(子目录不展开 —— 与第二层披露同口径:子目录按"名字+文件数"入表) */
7842
+ function listReferenceDocs(skillDir) {
7843
+ const dir = join(skillDir, REFERENCE_DIR);
7844
+ if (!existsSync(dir)) return [];
7845
+ return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".md")).map((e) => e.name).sort();
7846
+ }
7847
+ /**
7848
+ * 对一个 skill 目录跑 A3 档。
7849
+ * 🔴 三条判据各自**独立**(一条不过不掩盖另一条),全部机械、全部可复跑。
7850
+ */
7851
+ function analyzeSkillLayering(skillDir) {
7852
+ const skillMd = join(skillDir, "SKILL.md");
7853
+ const findings = [];
7854
+ if (!existsSync(skillMd)) return {
7855
+ hasSkillMd: false,
7856
+ topBodyBytes: 0,
7857
+ navBlockBytes: 0,
7858
+ navSelfDescriptions: [],
7859
+ referenceDocs: listReferenceDocs(skillDir),
7860
+ notNamedInTop: [],
7861
+ findings: [{
7862
+ code: "A3-1",
7863
+ detail: "没有 SKILL.md —— skill 的身份与顶层都无处安放"
7864
+ }],
7865
+ ok: false
7866
+ };
7867
+ const raw = readFileSync(skillMd, "utf-8");
7868
+ const [withoutNav, navBlockBytes] = stripNavBlock(stripFrontmatter(raw));
7869
+ const topBodyBytes = Buffer.byteLength(withoutNav.trim(), "utf-8");
7870
+ if (topBodyBytes < 2048) findings.push({
7871
+ code: "A3-1",
7872
+ detail: `顶层正文只有 ${topBodyBytes} B(< ${TOP_LAYER_MIN_BYTES})—— 顶层必须自己说清「身份与边界 / 用途与触发 / 领域模型(形状)/ 永远成立的约束 / 抽象树读法」,不能只列文件名把读者转手给下层(EAP:顶层说顶层的话)`
7873
+ });
7874
+ const navSelfDescriptions = [];
7875
+ for (const line of withoutNav.split("\n")) if (NAV_SELF_DESCRIPTION.test(line)) {
7876
+ const t = line.trim();
7877
+ navSelfDescriptions.push(t.length > 160 ? `${t.slice(0, 160)}…` : t);
7878
+ }
7879
+ if (navSelfDescriptions.length > 0) findings.push({
7880
+ code: "A3-2",
7881
+ detail: `顶层自称"只是导航层/只剩下导航" ×${navSelfDescriptions.length} —— 这是**树倒置的直接症状**:顶层声明自己什么都不说,读者拿不到任何上层陈述。修法 = 把下层的**顶层陈述**上提(hoist:从原处**删除并留指针**,一条内容只有一个家),不是加一句话辩解`
7882
+ });
7883
+ const referenceDocs = listReferenceDocs(skillDir);
7884
+ const notNamedInTop = referenceDocs.filter((d) => !raw.includes(d));
7885
+ if (notNamedInTop.length > 0) findings.push({
7886
+ code: "A3-3",
7887
+ detail: `references/ 下有 ${notNamedInTop.length} 件没在 SKILL.md 里点名:${notNamedInTop.join(" / ")} —— 顶层是**抽象树的地图**:不点名,读者就不知道存在这棵子树(第二层清单会自动补,但顶层该说"什么时候该下潜到哪一件")`
7888
+ });
7889
+ return {
7890
+ hasSkillMd: true,
7891
+ topBodyBytes,
7892
+ navBlockBytes,
7893
+ navSelfDescriptions,
7894
+ referenceDocs,
7895
+ notNamedInTop,
7896
+ findings,
7897
+ ok: findings.length === 0
7898
+ };
7899
+ }
7900
+ /** 渲染给人/模型看的一段(工具面直接用) */
7901
+ function formatLayeringReport(skillName, r) {
7902
+ const lines = [r.ok ? `✅ A3 分层档:通过(顶层正文 ${r.topBodyBytes} B / 导航块 ${r.navBlockBytes} B / 参考件 ${r.referenceDocs.length} 件全部点名)` : `❌ A3 分层档:${r.findings.length} 条不过`];
7903
+ for (const f of r.findings) lines.push(` · [${f.code}] ${f.detail}`);
7904
+ if (r.ok) lines.push(` (判据:顶层非桩 ≥ ${TOP_LAYER_MIN_BYTES} B / 顶层不自述"只是导航" / references/ 一级 .md 全部被点名)`);
7905
+ if (!r.ok) lines.push(" 👉 修完重跑 `check`。方法正文见 `guide` 的「分层抽象树」一节。");
7906
+ return lines.join("\n");
7907
+ }
7908
+ //#endregion
7722
7909
  //#region src/skills/skill-ontology.ts
7723
7910
  /**
7724
7911
  * skill-ontology.ts — **本体预留口**的发现与检查(纯逻辑,零 DSH 依赖)
@@ -7837,8 +8024,10 @@ function formatSkillOntologyInspection(skillName, insp) {
7837
8024
  *
7838
8025
  * 🔴 **三段分工(别混)**:
7839
8026
  * · **方法文本** = 本文件的 `SKILL_CREATOR_GUIDE`(`guide` 子命令印它)—— 给人/模型读"怎么做"。
7840
- * · **机械判据** = `src/skills/skill-ontology.ts`(P2)与 `src/skills/resource-index.ts`(P1)——
7841
- * 本工具**只做转发与呈现,绝不重写一遍检查**(同一件事的第二实现是本仓的老账)。
8027
+ * · **机械判据** = `src/skills/skill-ontology.ts`(P2 / **A1·A2 本体档**)、`src/skills/resource-index.ts`(P1)
8028
+ * 与 `src/skills/skill-layering.ts`(**A3 分层抽象树档** —— 2026-10-12 owner 令「确保未来创建和改进
8029
+ * skill 都保持 EAP 分层抽象树结构」)—— 本工具**只做转发与呈现,绝不重写一遍检查**(同一件事的
8030
+ * 第二实现是本仓的老账)。
7842
8031
  * · **语义档 C** = 引擎的 `compliance`(半机械:出逐条可回答问题清单,交 LLM/人在环回答)。
7843
8032
  *
7844
8033
  * 🔴 **J9:未建模 ≠ 异常。** 没有 `skill.ttl` 的**普通 skill** 全程无声 —— 本工具任何子命令都
@@ -7890,7 +8079,32 @@ const SKILL_CREATOR_GUIDE = `# serenity-skill —— 增强型 skill 的编写
7890
8079
  🔴 **相对路径由 \`create\` 算**(从本 skill 目录指向顶层 skill 的 references/),**不要人肉推**。
7891
8080
  🔴 引擎**只解析 \`owl:imports\`**;写 \`sr:imports\` **不会被读**,而且 \`check\` 对它**照样报全绿** ——
7892
8081
  所以别只看 \`check\` 绿就以为链上了(这正是本工具 \`check\` 要同时跑 A2 的原因)。
7893
- 3. 让 \`check\` 全绿(A1 结构合法 + A2 链上基础链)。
8082
+ 3. 让 \`check\` 全绿(**A1 结构合法 + A2 链上基础链**)。另有一档 **A3 分层抽象树**对**每个** skill
8083
+ 都适用(与有没有 ttl 无关)—— 见上面「分层抽象树」一节。
8084
+
8085
+ ## 分层抽象树(EAP)—— 顶层说顶层的话(🔴 2026-10-12 事故沉淀,机械档 A3 查它)
8086
+
8087
+ > ⚠️ **编号消歧**:本档的 **A3** 与 v1.54.0 记录里那个**已下线的旧 A3("引用可兑现")不是同一档** ——
8088
+ > 旧那条是照引擎源码"意图"推断的,**实测打假后不写了**;本条是 2026-10-12 **新立**的**分层形态**档。
8089
+
8090
+ skill 不是"一个文件 + 一堆参考件",而是一棵**按抽象层排的树**:
8091
+
8092
+ \`\`\`
8093
+ 第 0 层 SKILL.md ← 顶层:这是什么 / 边界 / 领域模型(形状)/ 永远成立的约束 / 怎么读下面
8094
+ 第 1 层 references/*.md ← 各子树:一件事一件(细节 / 沿革 / 清单 / 逐条读数)
8095
+ 第 2 层 各子树内的 H2/H3
8096
+ \`\`\`
8097
+
8098
+ 四条硬规矩(**A3 查前三条**):
8099
+
8100
+ 1. **顶层必须自己说顶层的话**:读 SKILL.md 就能重建「这是什么 / 骨架长什么样 / 哪些约束永远成立 /
8101
+ 细节去哪找」。🔴 **反例(真实事故)**:把 SKILL.md 切成几 KB 的"导航层"、顶层只列文件名 ——
8102
+ 这叫**树倒置**:顶层不再说顶层的话,读者拿不到任何上层陈述。
8103
+ 2. **顶层不许自称"只是导航层"**(A3-2):顶层声明自己什么都不说 ≡ 顶层空缺。
8104
+ 3. **顶层是地图**(A3-3):\`references/\` 下每一件都要**被点名**,并写清"什么时候该下潜到哪一件"。
8105
+ 4. **一条内容只有一个家**:细节下沉时**原处删掉并留指针**;把下层的顶层陈述**上提(hoist)**时同理。
8106
+ ⇒ 父层给**形状/抽象**、子层给**清单/细节**;父层**不复述**子层的清单,也**不含会漂的数**
8107
+ (版本 / 计数 / 测试基线 —— 那些留在单一真相源里)。
7894
8108
 
7895
8109
  ## 两层披露树的写法习惯(影响模型能不能找得到)
7896
8110
 
@@ -7912,7 +8126,8 @@ const SKILL_CREATOR_GUIDE = `# serenity-skill —— 增强型 skill 的编写
7912
8126
 
7913
8127
  \`\`\`
7914
8128
  serenity-skill-creator index <skill> ← 先看模型到底会看到什么(露没露、顺序对不对)
7915
- serenity-skill-creator check <skill> ← A1 结构 + A2 链上(机械,必须全绿)
8129
+ serenity-skill-creator check <skill> ← A3 分层(顶层非桩 / 不自述导航 / 点名各子树)+ A1 结构 + A2 链上
8130
+ (机械,必须全绿)
7916
8131
  serenity-skill-creator review <skill> ← C 档:文字与 ttl 逐条的合规问题清单(要人在环答)
7917
8132
  (改 SKILL.md / skill.ttl / references)
7918
8133
  ↑__________________________ 回到第一步
@@ -7965,21 +8180,50 @@ description: (一句话说清这个 skill 管什么、什么时候该加载它
7965
8180
 
7966
8181
  # Skill: ${name}
7967
8182
 
7968
- ## 用途
8183
+ > 一句话身份:本 skill 是<谁的><什么面>。
8184
+ > 🔴 **本文件是第 0 层(顶层)**:读完它就能重建「这是什么 / 骨架长什么样 / 哪些约束永远成立 / 细节去哪找」;
8185
+ > **细节不进正文**,按 §5 的树按需 \`read\` \`${REFERENCE_DIR}/\` 各子树。
8186
+
8187
+ ## 1. 身份与边界
8188
+
8189
+ | 项 | 内容 |
8190
+ |---|---|
8191
+ | **是什么** | (一句话) |
8192
+ | **管** | (本 skill 负责的领域) |
8193
+ | **不管** | (越界的事去哪 —— 指名上下游 skill) |
8194
+
8195
+ ## 2. 用途与触发条件
8196
+
8197
+ **用途**:(把"什么是这里最该一次读全的"写清)
8198
+
8199
+ **何时加载**(任一命中):
7969
8200
 
7970
- (这个领域是什么、管什么、不管什么)
8201
+ - (具体场景 1)
8202
+ - (具体场景 2)
7971
8203
 
7972
- ## 触发条件/何时加载
8204
+ ## 3. 领域模型(形状)
7973
8205
 
7974
- (什么情况下该加载本 skill)
8206
+ (这个领域的**顶层结构**:有哪几类东西、什么先于什么、什么永远成立。
8207
+ 🔴 **只给形状,不给清单** —— 清单会漂,且只该住在一处;有本体时真相源是同级 \`${SKILL_ONTOLOGY_FILE}\`。)
7975
8208
 
7976
- ## 领域结构
8209
+ ## 4. 永远成立的约束
7977
8210
 
7978
- (有本体时:本领域的类型与关系在这里只做**指路**,真相源是同级 \`${SKILL_ONTOLOGY_FILE}\`)
8211
+ 1. (违反了就算缺陷的规则,一条一行;每条给一句"为什么")
8212
+ 2. (会漂的值**不写死** —— 版本 / 计数 / 基线一律指向它们的单一真相源)
8213
+
8214
+ ## 5. 抽象树:怎么读这个 skill
8215
+
8216
+ 第 0 层 = 本文件;第 1 层 = \`${REFERENCE_DIR}/\` 各子树。**建一件就补一行**(顶层是地图):
8217
+
8218
+ | 子树 | 覆盖什么 | 什么时候下潜 |
8219
+ |---|---|---|
8220
+ | \`${REFERENCE_DIR}/00-xxx.md\` | (覆盖范围) | (触发场景) |
8221
+
8222
+ > 参考件**首个 \`#\` 标题**会被当作第二层索引里的摘要 ⇒ 给每个 .md 写一个说人话的首标题。
7979
8223
 
7980
8224
  ## 相关技能
7981
8225
 
7982
- (上下游 skill)
8226
+ (上下游 skill:谁先于本 skill、本 skill 产出给谁)
7983
8227
  `,
7984
8228
  [SKILL_ONTOLOGY_FILE]: `@prefix sr: <http://home-serenity/ontology#> .
7985
8229
  @prefix owl: <http://www.w3.org/2002/07/owl#> .
@@ -8006,7 +8250,7 @@ description: (一句话说清这个 skill 管什么、什么时候该加载它
8006
8250
  function createSkillCreatorTool() {
8007
8251
  return defineTool({
8008
8252
  name: "serenity-skill-creator",
8009
- description: "Creator for serenity-skills (this container's enhanced skill standard): write and optimize ontology-modeled skills. Subcommands: guide (the authoring/optimization method — read this first when creating or reworking a skill) / create <name> (scaffold a skill dir: SKILL.md + skill.ttl + references/, with the base-chain import path computed) / check <name> (A1 structural + A2 base-chain chained; three states — modeled-ok / plain-skill / modeled-but-check-could-not-run) / review <name> (C tier: axiom-vs-text compliance question list, half-mechanical — a human/LLM answers it) / index <name> (preview the second-layer resource list the model will actually see) / status (whole container: which skills are modeled, which are plain). A skill is \"modeled\" iff it has a file named exactly skill.ttl next to SKILL.md; a plain skill (no skill.ttl) is NOT an anomaly — it simply has no ontology. Only `create` writes, and it refuses to touch an existing skill directory.",
8253
+ description: "Creator for serenity-skills (this container's enhanced skill standard): write and optimize ontology-modeled skills. Subcommands: guide (the authoring/optimization method — read this first when creating or reworking a skill) / create <name> (scaffold a skill dir: SKILL.md + skill.ttl + references/, with the base-chain import path computed) / check <name> (A3 layering tier — applies to EVERY skill: the top layer must exist, must not be a bare nav stub, and must name every references/*.md; plus A1 structural + A2 base-chain for modeled skills) / review <name> (C tier: axiom-vs-text compliance question list, half-mechanical — a human/LLM answers it) / index <name> (preview the second-layer resource list the model will actually see) / status (whole container: which skills are modeled, which are plain). A skill is \"modeled\" iff it has a file named exactly skill.ttl next to SKILL.md; a plain skill (no skill.ttl) is NOT an anomaly — it simply has no ontology. Only `create` writes, and it refuses to touch an existing skill directory.",
8010
8254
  parameters: {
8011
8255
  action: {
8012
8256
  type: "string",
@@ -8049,11 +8293,18 @@ function createSkillCreatorTool() {
8049
8293
  if (insp.state === "ok") modeled.push(n);
8050
8294
  else broken.push(formatSkillOntologyInspection(n, insp));
8051
8295
  }
8296
+ const layeringFail = [];
8297
+ for (const n of names) {
8298
+ const rep = analyzeSkillLayering(join(root, ".opencode", "skills", n));
8299
+ if (!rep.ok) layeringFail.push(`${n}(${rep.findings.map((f) => f.code).join("/")})`);
8300
+ }
8052
8301
  return [
8053
8302
  `serenity-skill 一览(顶层 skill = ${readTopSkill(root)})`,
8054
8303
  `\n🧬 **已建模且通过** ${modeled.length} 个` + (modeled.length > 0 ? `:${modeled.join(", ")}` : ""),
8055
8304
  `\n⬜ **普通 skill(未建模)** ${plain.length} 个`,
8056
8305
  " ⚠️ 这**不是异常**,只是少一项能力(J9:增强对普通 skill 完全向后兼容)。",
8306
+ `\n📐 **A3 分层档**:${names.length - layeringFail.length} / ${names.length} 个通过` + (layeringFail.length > 0 ? `;未过 ${layeringFail.length} 个(**存量,非本次引入**):${layeringFail.slice(0, 12).join(", ")}${layeringFail.length > 12 ? ` …还有 ${layeringFail.length - 12} 个` : ""}
8307
+ 逐个看:\`check <name>\`(判据与修法见 \`guide\` 的「分层抽象树」一节)` : "(全部通过)"),
8057
8308
  broken.length > 0 ? `\n❌ **建模了但检查没跑成** ${broken.length} 个:\n${broken.join("\n")}` : ""
8058
8309
  ].filter((s) => s !== "").join("\n");
8059
8310
  }
@@ -8080,10 +8331,17 @@ function createSkillCreatorTool() {
8080
8331
  return idx === "" ? `${name}:**无参考件可列**(无 \`${REFERENCE_DIR}/\` 且无 \`${SKILL_ONTOLOGY_FILE}\`)⇒ 注入时**不产出**第二层块。` : `以下就是模型在提示词里**真正会看到**的第二层(只有清单,没有正文):\n\n${idx}`;
8081
8332
  }
8082
8333
  if (action === "check") {
8334
+ const layering = formatLayeringReport(name, analyzeSkillLayering(dir));
8083
8335
  const insp = inspectSkillOntology(dir, { root });
8084
8336
  const body = formatSkillOntologyInspection(name, insp);
8085
- if (insp.state === "none") return `${body}\n\n(要建模:\`serenity-skill-creator guide\` 看三个动作,或 \`create\` 生成骨架。)`;
8086
- return insp.state === "ok" ? `${body}\n\n👉 机械档过了。语义档(文字是否真遵守模型/公理)走 \`review\`。` : `${body}\n\n👉 修完**重跑本命令**(本仓教训:「检查没跑」与「检查通过」必须分得开)。`;
8337
+ if (insp.state === "none") return [
8338
+ layering,
8339
+ "",
8340
+ body,
8341
+ "",
8342
+ "(A1/A2 是**本体档**,未建模 ⇒ 不适用,这不是异常(J9)。要建模:`guide` 的「三个动作」,或 `create` 生成带骨架的 skill。)"
8343
+ ].join("\n");
8344
+ return insp.state === "ok" ? `${layering}\n\n${body}\n\n👉 A3 + A1/A2 都过了。语义档(文字是否真遵守模型/公理)走 \`review\`。` : `${layering}\n\n${body}\n\n👉 修完**重跑本命令**(本仓教训:「检查没跑」与「检查通过」必须分得开)。`;
8087
8345
  }
8088
8346
  const ttl = join(dir, SKILL_ONTOLOGY_FILE);
8089
8347
  if (!existsSync(ttl)) return formatSkillOntologyInspection(name, inspectSkillOntology(dir, { root })) + `\n\n(\`review\` 需要 \`${SKILL_ONTOLOGY_FILE}\`;普通 skill 没有可审的模型 —— 这不是错误。)`;
@@ -14585,9 +14843,11 @@ function registerOpencodeSkills(ctx) {
14585
14843
  for (const dir of listOpencodeSkillDirs(root)) {
14586
14844
  const skill = loadOpencodeSkill(dir);
14587
14845
  if (!skill || !skill.meta.name) continue;
14846
+ const baseDesc = skill.meta.description || "(opencode skill)";
14847
+ const nameSuffix = buildResourceNameSuffix(dir);
14588
14848
  candidates.push({
14589
14849
  name: skill.meta.name,
14590
- description: skill.meta.description || "(opencode skill)",
14850
+ description: nameSuffix ? `${baseDesc}${nameSuffix}` : baseDesc,
14591
14851
  ...skill.meta.whenToUse ? { whenToUse: skill.meta.whenToUse } : {},
14592
14852
  invocation: {
14593
14853
  modelInvocable: true,
@@ -7,6 +7,11 @@
7
7
  * 使 references/scripts 相对引用可解析。
8
8
  *
9
9
  * rank = 250:低于 project-dsh(100)与 custom(300)之间——本地 .dsh/skills 优先。
10
+ *
11
+ * 🔴 **本 provider 是第二层披露树的第四条落点所在**(2026-10-12,owner 裁决 O2):
12
+ * · `list()` = **目录面**(`available_skills` 的 `SkillSummary`)⇒ 参考件只能挂在 `description` 上(**只有名字**);
13
+ * · `get()` = **载入面**(`SkillDefinition.content`)⇒ 挂**完整索引**(名字 + 首标题 + 字节)。
14
+ * 两处**同源**(`src/skills/resource-index.ts`),不是各写一遍。
10
15
  */
11
16
  import type { Context } from 'cordis';
12
17
  export declare const OPENCODE_PROVIDER = "opencode-skills";
@@ -27,6 +27,16 @@
27
27
  * `references/*-domain.ttl`(旧名)一律当**普通参考件**:不特殊对待、不告警 —— 那 14 份由 CCC 自行改名。
28
28
  * 🔴 「未建模」不是异常(裁决 Q6 / 判据 J9):无 `skill.ttl` 的**普通 skill** 照常产出索引,
29
29
  * **零告警、零误差** —— 增强必须对普通 skill 完全向后兼容。
30
+ *
31
+ * 🔴 **两个面,两个入口**(2026-10-12 增;owner 裁决 O2)—— 同源、但成本形态不同:
32
+ * · **载入面** `buildResourceIndex()` —— 完整索引(名字 + 首标题 + 字节),带 `.md` 文件头读取;
33
+ * 在三条路径上各附一次:入口段(`system-prompt.ts` order −50)/轨迹段(`trajectory-skills.ts`
34
+ * order −45)/目录 provider 的 `get()`(`opencode-skills.ts`)。
35
+ * · **目录面** `buildResourceNameSuffix()` —— **只有名字**,**不读任何正文**;只挂一处:
36
+ * 目录 provider 的 `list()`(`available_skills` 的 `SkillSummary.description`)。
37
+ * 🔴 为什么目录面在这里:`SkillSummary` 契约里**没有列资源的位**(只有 name/description/whenToUse)
38
+ * ⇒ `description` 是唯一位置,且必须**自动生成**。
39
+ * ⇒ 两个面**共用** `collectEntries()`(范围 = 规则⑥只写一遍)。
30
40
  */
31
41
  /** 第二层占位口:本 skill 的本体约束文件(固定名,设计 §5.1) */
32
42
  export declare const SKILL_ONTOLOGY_FILE = "skill.ttl";
@@ -62,3 +72,26 @@ export declare function hasSkillOntology(skillDir: string): boolean;
62
72
  * ⇒ 整块不产出 —— 空标题是噪声)。调用方按"空串不产出该块"处理。
63
73
  */
64
74
  export declare function buildResourceIndex(skillDir: string, options?: ResourceIndexOptions): string;
75
+ /** 目录面(`SkillSummary.description`)用的名字清单 —— **只有名字**,无摘要、无字节 */
76
+ export interface ResourceNameList {
77
+ /** 条目的**基名**(目录带尾 `/`;本体文件就是 `skill.ttl`),按字节序 */
78
+ names: string[];
79
+ /** 因条数上限**没列出**的条数(`> 0` ⇒ 调用方必须**响亮**写出,规则③) */
80
+ hidden: number;
81
+ }
82
+ /**
83
+ * 收集**只有名字**的第二层清单(目录面专用)。
84
+ *
85
+ * 为什么单独一个入口(而不是复用 `buildResourceIndex`):**成本形态不同** ——
86
+ * 索引要给每个 `.md` 读文件头取摘要(规则④),而目录面是**每请求 × 每个 skill** 都要算的
87
+ * ⇒ 这条路径**一个字节正文都不读**(只 `readdir`/`stat`)。
88
+ * 范围仍与索引**同源**(共用 `collectEntries` ⇒ 规则⑥只有一个家)。
89
+ */
90
+ export declare function buildResourceNames(skillDir: string, options?: ResourceIndexOptions): ResourceNameList;
91
+ /**
92
+ * 目录面后缀:把名字清单拼成**可直接接在 `description` 后面**的一段文本。
93
+ *
94
+ * 🔴 **自动生成,绝不手写**(手写必与文件树漂);无可列项 ⇒ `''`(**普通 skill 零噪声** —— 判据 J9)。
95
+ * 🔴 **有界 + 响亮**(规则③):超上限时写出"另有 N 项",**绝不静默截断**。
96
+ */
97
+ export declare function buildResourceNameSuffix(skillDir: string, options?: ResourceIndexOptions): string;
@@ -0,0 +1,39 @@
1
+ /** 顶层正文(去掉 frontmatter 与生成的导航块)的**下限**:低于它 = 顶层只是桩 */
2
+ export declare const TOP_LAYER_MIN_BYTES = 2048;
3
+ /** 生成块(第二层清单)的哨兵 —— 它由 `skill-lint split` / 生成器产出,**不算顶层正文** */
4
+ export declare const NAV_BLOCK_BEGIN = "<!-- skill-lint:split-nav -->";
5
+ export declare const NAV_BLOCK_END = "<!-- /skill-lint:split-nav -->";
6
+ /**
7
+ * "本文件只是导航层"这类**自述** —— 它是树倒置的**直接症状**(顶层自己声明什么都不说)。
8
+ * 正常 skill 不会写这句话 ⇒ 这条判据**几乎不会假阳**。
9
+ */
10
+ export declare const NAV_SELF_DESCRIPTION: RegExp;
11
+ export interface LayeringFinding {
12
+ code: 'A3-1' | 'A3-2' | 'A3-3';
13
+ detail: string;
14
+ }
15
+ export interface LayeringReport {
16
+ /** 是否有 SKILL.md */
17
+ hasSkillMd: boolean;
18
+ /** 顶层正文字节(已扣 frontmatter 与导航块) */
19
+ topBodyBytes: number;
20
+ /** 被扣掉的导航块字节(用于自证扣了什么) */
21
+ navBlockBytes: number;
22
+ /** A3-2 命中行(原文,截断展示) */
23
+ navSelfDescriptions: string[];
24
+ /** references/ 一级下的 .md 名单 */
25
+ referenceDocs: string[];
26
+ /** A3-3:顶层全文里**没被点名**的参考件 */
27
+ notNamedInTop: string[];
28
+ findings: LayeringFinding[];
29
+ ok: boolean;
30
+ }
31
+ /** references/ **一级**下的 .md(子目录不展开 —— 与第二层披露同口径:子目录按"名字+文件数"入表) */
32
+ export declare function listReferenceDocs(skillDir: string): string[];
33
+ /**
34
+ * 对一个 skill 目录跑 A3 档。
35
+ * 🔴 三条判据各自**独立**(一条不过不掩盖另一条),全部机械、全部可复跑。
36
+ */
37
+ export declare function analyzeSkillLayering(skillDir: string): LayeringReport;
38
+ /** 渲染给人/模型看的一段(工具面直接用) */
39
+ export declare function formatLayeringReport(skillName: string, r: LayeringReport): string;
@@ -4,5 +4,5 @@
4
4
  * 边界(D23):**本文只是方法**;判据在代码里(P1/P2),语义审查在引擎的 `compliance` 里 ——
5
5
  * 三者**不许互相抄**(同一件事写两遍必然漂移)。
6
6
  */
7
- export declare const SKILL_CREATOR_GUIDE = "# serenity-skill \u2014\u2014 \u589E\u5F3A\u578B skill \u7684\u7F16\u5199\u4E0E\u4F18\u5316\u65B9\u6CD5\n\n## \u4F55\u65F6\u8BE5\u5EFA\u6A21\uFF0C\u4F55\u65F6\u4E0D\u8BE5\n\n**\u8BE5\u5EFA\u6A21**\uFF1A\u8BE5\u9886\u57DF\u6709**\u7A33\u5B9A\u7684\u7C7B\u578B\u4E0E\u5173\u7CFB**\uFF08\u8C01\u662F\u8C01\u3001\u4E00\u5BF9\u591A\u3001\u4EC0\u4E48\u5FC5\u987B\u5148\u4E8E\u4EC0\u4E48\uFF09\uFF0C\u4E14\u8FD9\u4E9B\u7ED3\u6784**\u4F1A\u53CD\u590D\u88AB\u5F15\u7528**\n\uFF08\u6392\u9519\u3001\u5BA1\u67E5\u3001\u5199\u6587\u6863\u90FD\u8981\u56DE\u53BB\u770B\u5B83\uFF09\u2014\u2014 \u5178\u578B\u5982\"\u4E00\u4E2A skill \u7BA1\u54EA\u4E9B\u8D44\u4EA7\u3001\u8D44\u4EA7\u4E4B\u95F4\u4EC0\u4E48\u7EA6\u675F\"\u3002\n\n**\u4E0D\u8BE5\u5EFA\u6A21**\uFF08**\u4E0D\u5EFA\u6A21\u4E0D\u662F\u7F3A\u9677**\uFF09\uFF1A\n\u00B7 \u7EAF\u64CD\u4F5C\u89C4\u7A0B\uFF08\"\u5148\u8DD1 A \u518D\u8DD1 B\"\uFF09\u2014\u2014 \u90A3\u662F SKILL.md \u7684\u6B63\u6587\uFF0C\u7ED9\u5B83\u5957\u672C\u4F53\u53EA\u662F\u6362\u4E2A\u5730\u65B9\u5199\u6563\u6587\uFF1B\n\u00B7 \u4E00\u6B21\u6027/\u77ED\u547D\u7684\u4E8B\uFF1B\n\u00B7 \u4F60\u81EA\u5DF1\u90FD\u8FD8\u8BF4\u4E0D\u6E05\u9886\u57DF\u91CC\u5230\u5E95\u6709\u54EA\u51E0\u7C7B\u4E1C\u897F\u65F6 \u2014\u2014 **\u5148\u5199\u6563\u6587\uFF0C\u7B49\u7ED3\u6784\u6D6E\u73B0\u518D\u5EFA\u6A21**\uFF08\u5EFA\u6A21\u4E0D\u662F\u5165\u573A\u5238\uFF09\u3002\n\n## \u4E09\u4E2A\u52A8\u4F5C\uFF08\u505A\u5B8C\u5373\"\u5DF2\u5EFA\u6A21\"\uFF09\n\n1. \u5728 skill \u76EE\u5F55\u653E**\u56FA\u5B9A\u540D** `skill.ttl`\uFF08\u4E0E `SKILL.md` \u5E76\u5217\uFF09\u2014\u2014 \u8FD9\u662F**\u552F\u4E00**\u88AB\u8BA4\u7684\u540D\u5B57\u3002\n \u26A0\uFE0F \u65E7\u5199\u6CD5 `references/<name>-domain.ttl` **\u4E0D\u88AB\u8BA4**\uFF08\u9759\u9ED8\u5F53\u666E\u901A\u53C2\u8003\u4EF6\uFF09\uFF1A\u4E0D\u662F\u62A5\u9519\uFF0C\u662F**\u6CA1\u6709\u4EBA\u4F1A\u770B\u5B83**\u3002\n2. `skill.ttl` **\u5FC5\u987B\u94FE\u4E0A\u57FA\u7840\u94FE**\uFF0C\u5F62\u5F0F\u662F `owl:imports <\u76F8\u5BF9\u8DEF\u5F84>`\uFF1A\n ```turtle\n :onto a owl:Ontology ;\n sr:name \"<skill-name>\" ;\n owl:versionInfo \"0.1.0\" ;\n owl:imports <../home-serenity/references/serenity-skills-ontology.ttl> .\n ```\n \uD83D\uDD34 **\u76F8\u5BF9\u8DEF\u5F84\u7531 `create` \u7B97**\uFF08\u4ECE\u672C skill \u76EE\u5F55\u6307\u5411\u9876\u5C42 skill \u7684 references/\uFF09\uFF0C**\u4E0D\u8981\u4EBA\u8089\u63A8**\u3002\n \uD83D\uDD34 \u5F15\u64CE**\u53EA\u89E3\u6790 `owl:imports`**\uFF1B\u5199 `sr:imports` **\u4E0D\u4F1A\u88AB\u8BFB**\uFF0C\u800C\u4E14 `check` \u5BF9\u5B83**\u7167\u6837\u62A5\u5168\u7EFF** \u2014\u2014\n \u6240\u4EE5\u522B\u53EA\u770B `check` \u7EFF\u5C31\u4EE5\u4E3A\u94FE\u4E0A\u4E86\uFF08\u8FD9\u6B63\u662F\u672C\u5DE5\u5177 `check` \u8981\u540C\u65F6\u8DD1 A2 \u7684\u539F\u56E0\uFF09\u3002\n3. \u8BA9 `check` \u5168\u7EFF\uFF08A1 \u7ED3\u6784\u5408\u6CD5 \uFF0B A2 \u94FE\u4E0A\u57FA\u7840\u94FE\uFF09\u3002\n\n## \u4E24\u5C42\u62AB\u9732\u6811\u7684\u5199\u6CD5\u4E60\u60EF\uFF08\u5F71\u54CD\u6A21\u578B\u80FD\u4E0D\u80FD\u627E\u5F97\u5230\uFF09\n\n\u00B7 `references/` \u91CC\u7684\u6587\u4EF6\u540D**\u5C31\u662F\u76EE\u5F55**\uFF1A\u524D\u7F00\u6570\u5B57\uFF08`00-`\u2026`90-`\uFF09\u7ED9\u7A33\u5B9A\u6B21\u5E8F\uFF0C\u540D\u5B57**\u5199\u6210\u80FD\u8BFB\u61C2\u7684\u4E00\u53E5**\u3002\n\u00B7 \u6BCF\u4E2A\u53C2\u8003\u6587\u4EF6\u7684**\u9996\u4E2A `#` \u6807\u9898**\u4F1A\u88AB\u5F53\u4F5C\u7D22\u5F15\u91CC\u7684\u6458\u8981 \u21D2 **\u7ED9\u6BCF\u4E2A .md \u5199\u4E00\u4E2A\u8BF4\u4EBA\u8BDD\u7684\u9996\u6807\u9898**\uFF08\u522B\u5199\u6587\u4EF6\u540D\u590D\u8BFB\uFF09\u3002\n\u00B7 \u7D22\u5F15**\u53EA\u5217\u4E0D\u8BFB**\uFF1A\u6B63\u6587\u6C38\u8FDC\u7559\u7ED9\u6309\u9700 `read` \u21D2 \u522B\u628A\u5927\u6BB5\u5185\u5BB9\u585E\u8FDB SKILL.md\uFF08\u5B83\u6BCF\u8BF7\u6C42\u90FD\u6CE8\u5165\uFF09\u3002\n\u00B7 `references/` \u4E0B\u7684**\u5B50\u76EE\u5F55**\u4F1A\u88AB\u5217\u6210\u4E00\u884C\uFF08\u540D\u5B57\uFF0B\u6587\u4EF6\u6570\uFF09\uFF0C**\u4E0D\u5C55\u5F00** \u21D2 \u76EE\u5F55\u540D\u8981\u8D77\u5F97\u8BA9\u4EBA\u77E5\u9053\u91CC\u9762\u662F\u4EC0\u4E48\u3002\n\n## \u4ECE\u9886\u57DF\u6563\u6587\u5230 ttl\uFF08\u5177\u4F53\u6B65\u9AA4\uFF09\n\n1. \u628A SKILL.md \u91CC\u7684\u540D\u8BCD\u5708\u51FA\u6765 \u2192 \u6311\u51FA**\u53CD\u590D\u51FA\u73B0\u3001\u6709\u8EAB\u4EFD**\u7684\u90A3\u4E9B = \u5019\u9009\u7C7B\u578B\uFF1B\n2. \u7ED9\u6BCF\u4E2A\u7C7B\u578B\u5199\uFF1A`rdfs:label` \uFF0B `sr:rigidity`\uFF08`rigid` \u8EAB\u4EFD\u56FA\u5B9A\uFF0F`anti-rigid` \u4F1A\u53D8\uFF09\uFF0B \u8EAB\u4EFD\u5C5E\u6027\uFF08`sr:identity`\uFF09\uFF1B\n3. \u628A\u52A8\u8BCD\u5708\u51FA\u6765 \u2192 \u6709\u65B9\u5411\u3001\u6709\u57FA\u6570\u7684 = \u5173\u7CFB\uFF08`rdfs:domain`/`rdfs:range` \uFF0B `sr:cardinality`\uFF09\uFF1B\n4. \u628A\"\u6C38\u8FDC\u6210\u7ACB\u7684\u8BDD\"\u5199\u6210\u516C\u7406\uFF08`sr:axiom`\uFF09\u2014\u2014 **\u53EA\u5199\u771F\u80FD\u5224\u771F\u5047\u7684**\uFF0C\u522B\u5199\u53E3\u53F7\uFF1B\n5. \u8865 `sr:source`/\u6765\u6E90\uFF08\u5BF9\u5916\u90E8\u4E3B\u5F20\uFF09\u3002\n**\u65B9\u6CD5\u6B63\u6587\u4E0D\u5728\u8FD9\u91CC\u91CD\u590D**\uFF1A\u89C1 `praxis ontology`\uFF08\u672C\u4F53\u5DE5\u7A0B\u65B9\u6CD5\u7FA4\uFF1A\u56DB\u7EC4\u5224\u636E M1\u2013M10\uFF0FL1\u2013L5\uFF0FD1\u2013D8\uFF0FV1\u2013V4\u3001OEPE \u56DE\u8DEF\u3001\u53CD\u6A21\u5F0F\uFF09\u3002\n\n## \u4F18\u5316\u56DE\u8DEF\uFF08\u6539\u5B8C\u4E4B\u540E\u518D\u8D70\u4E00\u904D\uFF09\n\n```\nserenity-skill-creator index <skill> \u2190 \u5148\u770B\u6A21\u578B\u5230\u5E95\u4F1A\u770B\u5230\u4EC0\u4E48\uFF08\u9732\u6CA1\u9732\u3001\u987A\u5E8F\u5BF9\u4E0D\u5BF9\uFF09\nserenity-skill-creator check <skill> \u2190 A1 \u7ED3\u6784 \uFF0B A2 \u94FE\u4E0A\uFF08\u673A\u68B0\uFF0C\u5FC5\u987B\u5168\u7EFF\uFF09\nserenity-skill-creator review <skill> \u2190 C \u6863\uFF1A\u6587\u5B57\u4E0E ttl \u9010\u6761\u7684\u5408\u89C4\u95EE\u9898\u6E05\u5355\uFF08\u8981\u4EBA\u5728\u73AF\u7B54\uFF09\n\uFF08\u6539 SKILL.md / skill.ttl / references\uFF09\n \u2191__________________________ \u56DE\u5230\u7B2C\u4E00\u6B65\n```\n\n**\u5224\u636E**\uFF1A\u6539\u5B8C**\u5FC5\u987B\u91CD\u8DD1** `check` \u2014\u2014 \u672C\u4ED3\u7684\u6559\u8BAD\u662F\"\u68C0\u67E5\u6CA1\u8DD1\"\u548C\"\u68C0\u67E5\u901A\u8FC7\"\u5728\u8F93\u51FA\u4E0A\u5FC5\u987B\u5206\u5F97\u5F00\uFF1B\n`review` \u51FA\u7684\u662F**\u95EE\u9898\u6E05\u5355**\uFF08\u534A\u673A\u68B0\u3001\u8981\u4EBA\u56DE\u7B54\uFF09\uFF0C**\u4E0D\u662F**\u901A\u8FC7/\u4E0D\u901A\u8FC7\u3002\n";
7
+ export declare const SKILL_CREATOR_GUIDE = "# serenity-skill \u2014\u2014 \u589E\u5F3A\u578B skill \u7684\u7F16\u5199\u4E0E\u4F18\u5316\u65B9\u6CD5\n\n## \u4F55\u65F6\u8BE5\u5EFA\u6A21\uFF0C\u4F55\u65F6\u4E0D\u8BE5\n\n**\u8BE5\u5EFA\u6A21**\uFF1A\u8BE5\u9886\u57DF\u6709**\u7A33\u5B9A\u7684\u7C7B\u578B\u4E0E\u5173\u7CFB**\uFF08\u8C01\u662F\u8C01\u3001\u4E00\u5BF9\u591A\u3001\u4EC0\u4E48\u5FC5\u987B\u5148\u4E8E\u4EC0\u4E48\uFF09\uFF0C\u4E14\u8FD9\u4E9B\u7ED3\u6784**\u4F1A\u53CD\u590D\u88AB\u5F15\u7528**\n\uFF08\u6392\u9519\u3001\u5BA1\u67E5\u3001\u5199\u6587\u6863\u90FD\u8981\u56DE\u53BB\u770B\u5B83\uFF09\u2014\u2014 \u5178\u578B\u5982\"\u4E00\u4E2A skill \u7BA1\u54EA\u4E9B\u8D44\u4EA7\u3001\u8D44\u4EA7\u4E4B\u95F4\u4EC0\u4E48\u7EA6\u675F\"\u3002\n\n**\u4E0D\u8BE5\u5EFA\u6A21**\uFF08**\u4E0D\u5EFA\u6A21\u4E0D\u662F\u7F3A\u9677**\uFF09\uFF1A\n\u00B7 \u7EAF\u64CD\u4F5C\u89C4\u7A0B\uFF08\"\u5148\u8DD1 A \u518D\u8DD1 B\"\uFF09\u2014\u2014 \u90A3\u662F SKILL.md \u7684\u6B63\u6587\uFF0C\u7ED9\u5B83\u5957\u672C\u4F53\u53EA\u662F\u6362\u4E2A\u5730\u65B9\u5199\u6563\u6587\uFF1B\n\u00B7 \u4E00\u6B21\u6027/\u77ED\u547D\u7684\u4E8B\uFF1B\n\u00B7 \u4F60\u81EA\u5DF1\u90FD\u8FD8\u8BF4\u4E0D\u6E05\u9886\u57DF\u91CC\u5230\u5E95\u6709\u54EA\u51E0\u7C7B\u4E1C\u897F\u65F6 \u2014\u2014 **\u5148\u5199\u6563\u6587\uFF0C\u7B49\u7ED3\u6784\u6D6E\u73B0\u518D\u5EFA\u6A21**\uFF08\u5EFA\u6A21\u4E0D\u662F\u5165\u573A\u5238\uFF09\u3002\n\n## \u4E09\u4E2A\u52A8\u4F5C\uFF08\u505A\u5B8C\u5373\"\u5DF2\u5EFA\u6A21\"\uFF09\n\n1. \u5728 skill \u76EE\u5F55\u653E**\u56FA\u5B9A\u540D** `skill.ttl`\uFF08\u4E0E `SKILL.md` \u5E76\u5217\uFF09\u2014\u2014 \u8FD9\u662F**\u552F\u4E00**\u88AB\u8BA4\u7684\u540D\u5B57\u3002\n \u26A0\uFE0F \u65E7\u5199\u6CD5 `references/<name>-domain.ttl` **\u4E0D\u88AB\u8BA4**\uFF08\u9759\u9ED8\u5F53\u666E\u901A\u53C2\u8003\u4EF6\uFF09\uFF1A\u4E0D\u662F\u62A5\u9519\uFF0C\u662F**\u6CA1\u6709\u4EBA\u4F1A\u770B\u5B83**\u3002\n2. `skill.ttl` **\u5FC5\u987B\u94FE\u4E0A\u57FA\u7840\u94FE**\uFF0C\u5F62\u5F0F\u662F `owl:imports <\u76F8\u5BF9\u8DEF\u5F84>`\uFF1A\n ```turtle\n :onto a owl:Ontology ;\n sr:name \"<skill-name>\" ;\n owl:versionInfo \"0.1.0\" ;\n owl:imports <../home-serenity/references/serenity-skills-ontology.ttl> .\n ```\n \uD83D\uDD34 **\u76F8\u5BF9\u8DEF\u5F84\u7531 `create` \u7B97**\uFF08\u4ECE\u672C skill \u76EE\u5F55\u6307\u5411\u9876\u5C42 skill \u7684 references/\uFF09\uFF0C**\u4E0D\u8981\u4EBA\u8089\u63A8**\u3002\n \uD83D\uDD34 \u5F15\u64CE**\u53EA\u89E3\u6790 `owl:imports`**\uFF1B\u5199 `sr:imports` **\u4E0D\u4F1A\u88AB\u8BFB**\uFF0C\u800C\u4E14 `check` \u5BF9\u5B83**\u7167\u6837\u62A5\u5168\u7EFF** \u2014\u2014\n \u6240\u4EE5\u522B\u53EA\u770B `check` \u7EFF\u5C31\u4EE5\u4E3A\u94FE\u4E0A\u4E86\uFF08\u8FD9\u6B63\u662F\u672C\u5DE5\u5177 `check` \u8981\u540C\u65F6\u8DD1 A2 \u7684\u539F\u56E0\uFF09\u3002\n3. \u8BA9 `check` \u5168\u7EFF\uFF08**A1 \u7ED3\u6784\u5408\u6CD5 \uFF0B A2 \u94FE\u4E0A\u57FA\u7840\u94FE**\uFF09\u3002\u53E6\u6709\u4E00\u6863 **A3 \u5206\u5C42\u62BD\u8C61\u6811**\u5BF9**\u6BCF\u4E2A** skill\n \u90FD\u9002\u7528\uFF08\u4E0E\u6709\u6CA1\u6709 ttl \u65E0\u5173\uFF09\u2014\u2014 \u89C1\u4E0A\u9762\u300C\u5206\u5C42\u62BD\u8C61\u6811\u300D\u4E00\u8282\u3002\n\n## \u5206\u5C42\u62BD\u8C61\u6811\uFF08EAP\uFF09\u2014\u2014 \u9876\u5C42\u8BF4\u9876\u5C42\u7684\u8BDD\uFF08\uD83D\uDD34 2026-10-12 \u4E8B\u6545\u6C89\u6DC0\uFF0C\u673A\u68B0\u6863 A3 \u67E5\u5B83\uFF09\n\n> \u26A0\uFE0F **\u7F16\u53F7\u6D88\u6B67**\uFF1A\u672C\u6863\u7684 **A3** \u4E0E v1.54.0 \u8BB0\u5F55\u91CC\u90A3\u4E2A**\u5DF2\u4E0B\u7EBF\u7684\u65E7 A3\uFF08\"\u5F15\u7528\u53EF\u5151\u73B0\"\uFF09\u4E0D\u662F\u540C\u4E00\u6863** \u2014\u2014\n> \u65E7\u90A3\u6761\u662F\u7167\u5F15\u64CE\u6E90\u7801\"\u610F\u56FE\"\u63A8\u65AD\u7684\uFF0C**\u5B9E\u6D4B\u6253\u5047\u540E\u4E0D\u5199\u4E86**\uFF1B\u672C\u6761\u662F 2026-10-12 **\u65B0\u7ACB**\u7684**\u5206\u5C42\u5F62\u6001**\u6863\u3002\n\nskill \u4E0D\u662F\"\u4E00\u4E2A\u6587\u4EF6 \uFF0B \u4E00\u5806\u53C2\u8003\u4EF6\"\uFF0C\u800C\u662F\u4E00\u68F5**\u6309\u62BD\u8C61\u5C42\u6392\u7684\u6811**\uFF1A\n\n```\n\u7B2C 0 \u5C42 SKILL.md \u2190 \u9876\u5C42\uFF1A\u8FD9\u662F\u4EC0\u4E48 \uFF0F \u8FB9\u754C \uFF0F \u9886\u57DF\u6A21\u578B\uFF08\u5F62\u72B6\uFF09\uFF0F \u6C38\u8FDC\u6210\u7ACB\u7684\u7EA6\u675F \uFF0F \u600E\u4E48\u8BFB\u4E0B\u9762\n\u7B2C 1 \u5C42 references/*.md \u2190 \u5404\u5B50\u6811\uFF1A\u4E00\u4EF6\u4E8B\u4E00\u4EF6\uFF08\u7EC6\u8282 \uFF0F \u6CBF\u9769 \uFF0F \u6E05\u5355 \uFF0F \u9010\u6761\u8BFB\u6570\uFF09\n\u7B2C 2 \u5C42 \u5404\u5B50\u6811\u5185\u7684 H2/H3\n```\n\n\u56DB\u6761\u786C\u89C4\u77E9\uFF08**A3 \u67E5\u524D\u4E09\u6761**\uFF09\uFF1A\n\n1. **\u9876\u5C42\u5FC5\u987B\u81EA\u5DF1\u8BF4\u9876\u5C42\u7684\u8BDD**\uFF1A\u8BFB SKILL.md \u5C31\u80FD\u91CD\u5EFA\u300C\u8FD9\u662F\u4EC0\u4E48 \uFF0F \u9AA8\u67B6\u957F\u4EC0\u4E48\u6837 \uFF0F \u54EA\u4E9B\u7EA6\u675F\u6C38\u8FDC\u6210\u7ACB \uFF0F\n \u7EC6\u8282\u53BB\u54EA\u627E\u300D\u3002\uD83D\uDD34 **\u53CD\u4F8B\uFF08\u771F\u5B9E\u4E8B\u6545\uFF09**\uFF1A\u628A SKILL.md \u5207\u6210\u51E0 KB \u7684\"\u5BFC\u822A\u5C42\"\u3001\u9876\u5C42\u53EA\u5217\u6587\u4EF6\u540D \u2014\u2014\n \u8FD9\u53EB**\u6811\u5012\u7F6E**\uFF1A\u9876\u5C42\u4E0D\u518D\u8BF4\u9876\u5C42\u7684\u8BDD\uFF0C\u8BFB\u8005\u62FF\u4E0D\u5230\u4EFB\u4F55\u4E0A\u5C42\u9648\u8FF0\u3002\n2. **\u9876\u5C42\u4E0D\u8BB8\u81EA\u79F0\"\u53EA\u662F\u5BFC\u822A\u5C42\"**\uFF08A3-2\uFF09\uFF1A\u9876\u5C42\u58F0\u660E\u81EA\u5DF1\u4EC0\u4E48\u90FD\u4E0D\u8BF4 \u2261 \u9876\u5C42\u7A7A\u7F3A\u3002\n3. **\u9876\u5C42\u662F\u5730\u56FE**\uFF08A3-3\uFF09\uFF1A`references/` \u4E0B\u6BCF\u4E00\u4EF6\u90FD\u8981**\u88AB\u70B9\u540D**\uFF0C\u5E76\u5199\u6E05\"\u4EC0\u4E48\u65F6\u5019\u8BE5\u4E0B\u6F5C\u5230\u54EA\u4E00\u4EF6\"\u3002\n4. **\u4E00\u6761\u5185\u5BB9\u53EA\u6709\u4E00\u4E2A\u5BB6**\uFF1A\u7EC6\u8282\u4E0B\u6C89\u65F6**\u539F\u5904\u5220\u6389\u5E76\u7559\u6307\u9488**\uFF1B\u628A\u4E0B\u5C42\u7684\u9876\u5C42\u9648\u8FF0**\u4E0A\u63D0\uFF08hoist\uFF09**\u65F6\u540C\u7406\u3002\n \u21D2 \u7236\u5C42\u7ED9**\u5F62\u72B6/\u62BD\u8C61**\u3001\u5B50\u5C42\u7ED9**\u6E05\u5355/\u7EC6\u8282**\uFF1B\u7236\u5C42**\u4E0D\u590D\u8FF0**\u5B50\u5C42\u7684\u6E05\u5355\uFF0C\u4E5F**\u4E0D\u542B\u4F1A\u6F02\u7684\u6570**\n \uFF08\u7248\u672C \uFF0F \u8BA1\u6570 \uFF0F \u6D4B\u8BD5\u57FA\u7EBF \u2014\u2014 \u90A3\u4E9B\u7559\u5728\u5355\u4E00\u771F\u76F8\u6E90\u91CC\uFF09\u3002\n\n## \u4E24\u5C42\u62AB\u9732\u6811\u7684\u5199\u6CD5\u4E60\u60EF\uFF08\u5F71\u54CD\u6A21\u578B\u80FD\u4E0D\u80FD\u627E\u5F97\u5230\uFF09\n\n\u00B7 `references/` \u91CC\u7684\u6587\u4EF6\u540D**\u5C31\u662F\u76EE\u5F55**\uFF1A\u524D\u7F00\u6570\u5B57\uFF08`00-`\u2026`90-`\uFF09\u7ED9\u7A33\u5B9A\u6B21\u5E8F\uFF0C\u540D\u5B57**\u5199\u6210\u80FD\u8BFB\u61C2\u7684\u4E00\u53E5**\u3002\n\u00B7 \u6BCF\u4E2A\u53C2\u8003\u6587\u4EF6\u7684**\u9996\u4E2A `#` \u6807\u9898**\u4F1A\u88AB\u5F53\u4F5C\u7D22\u5F15\u91CC\u7684\u6458\u8981 \u21D2 **\u7ED9\u6BCF\u4E2A .md \u5199\u4E00\u4E2A\u8BF4\u4EBA\u8BDD\u7684\u9996\u6807\u9898**\uFF08\u522B\u5199\u6587\u4EF6\u540D\u590D\u8BFB\uFF09\u3002\n\u00B7 \u7D22\u5F15**\u53EA\u5217\u4E0D\u8BFB**\uFF1A\u6B63\u6587\u6C38\u8FDC\u7559\u7ED9\u6309\u9700 `read` \u21D2 \u522B\u628A\u5927\u6BB5\u5185\u5BB9\u585E\u8FDB SKILL.md\uFF08\u5B83\u6BCF\u8BF7\u6C42\u90FD\u6CE8\u5165\uFF09\u3002\n\u00B7 `references/` \u4E0B\u7684**\u5B50\u76EE\u5F55**\u4F1A\u88AB\u5217\u6210\u4E00\u884C\uFF08\u540D\u5B57\uFF0B\u6587\u4EF6\u6570\uFF09\uFF0C**\u4E0D\u5C55\u5F00** \u21D2 \u76EE\u5F55\u540D\u8981\u8D77\u5F97\u8BA9\u4EBA\u77E5\u9053\u91CC\u9762\u662F\u4EC0\u4E48\u3002\n\n## \u4ECE\u9886\u57DF\u6563\u6587\u5230 ttl\uFF08\u5177\u4F53\u6B65\u9AA4\uFF09\n\n1. \u628A SKILL.md \u91CC\u7684\u540D\u8BCD\u5708\u51FA\u6765 \u2192 \u6311\u51FA**\u53CD\u590D\u51FA\u73B0\u3001\u6709\u8EAB\u4EFD**\u7684\u90A3\u4E9B = \u5019\u9009\u7C7B\u578B\uFF1B\n2. \u7ED9\u6BCF\u4E2A\u7C7B\u578B\u5199\uFF1A`rdfs:label` \uFF0B `sr:rigidity`\uFF08`rigid` \u8EAB\u4EFD\u56FA\u5B9A\uFF0F`anti-rigid` \u4F1A\u53D8\uFF09\uFF0B \u8EAB\u4EFD\u5C5E\u6027\uFF08`sr:identity`\uFF09\uFF1B\n3. \u628A\u52A8\u8BCD\u5708\u51FA\u6765 \u2192 \u6709\u65B9\u5411\u3001\u6709\u57FA\u6570\u7684 = \u5173\u7CFB\uFF08`rdfs:domain`/`rdfs:range` \uFF0B `sr:cardinality`\uFF09\uFF1B\n4. \u628A\"\u6C38\u8FDC\u6210\u7ACB\u7684\u8BDD\"\u5199\u6210\u516C\u7406\uFF08`sr:axiom`\uFF09\u2014\u2014 **\u53EA\u5199\u771F\u80FD\u5224\u771F\u5047\u7684**\uFF0C\u522B\u5199\u53E3\u53F7\uFF1B\n5. \u8865 `sr:source`/\u6765\u6E90\uFF08\u5BF9\u5916\u90E8\u4E3B\u5F20\uFF09\u3002\n**\u65B9\u6CD5\u6B63\u6587\u4E0D\u5728\u8FD9\u91CC\u91CD\u590D**\uFF1A\u89C1 `praxis ontology`\uFF08\u672C\u4F53\u5DE5\u7A0B\u65B9\u6CD5\u7FA4\uFF1A\u56DB\u7EC4\u5224\u636E M1\u2013M10\uFF0FL1\u2013L5\uFF0FD1\u2013D8\uFF0FV1\u2013V4\u3001OEPE \u56DE\u8DEF\u3001\u53CD\u6A21\u5F0F\uFF09\u3002\n\n## \u4F18\u5316\u56DE\u8DEF\uFF08\u6539\u5B8C\u4E4B\u540E\u518D\u8D70\u4E00\u904D\uFF09\n\n```\nserenity-skill-creator index <skill> \u2190 \u5148\u770B\u6A21\u578B\u5230\u5E95\u4F1A\u770B\u5230\u4EC0\u4E48\uFF08\u9732\u6CA1\u9732\u3001\u987A\u5E8F\u5BF9\u4E0D\u5BF9\uFF09\nserenity-skill-creator check <skill> \u2190 A3 \u5206\u5C42\uFF08\u9876\u5C42\u975E\u6869 \uFF0F \u4E0D\u81EA\u8FF0\u5BFC\u822A \uFF0F \u70B9\u540D\u5404\u5B50\u6811\uFF09\uFF0B A1 \u7ED3\u6784 \uFF0B A2 \u94FE\u4E0A\n \uFF08\u673A\u68B0\uFF0C\u5FC5\u987B\u5168\u7EFF\uFF09\nserenity-skill-creator review <skill> \u2190 C \u6863\uFF1A\u6587\u5B57\u4E0E ttl \u9010\u6761\u7684\u5408\u89C4\u95EE\u9898\u6E05\u5355\uFF08\u8981\u4EBA\u5728\u73AF\u7B54\uFF09\n\uFF08\u6539 SKILL.md / skill.ttl / references\uFF09\n \u2191__________________________ \u56DE\u5230\u7B2C\u4E00\u6B65\n```\n\n**\u5224\u636E**\uFF1A\u6539\u5B8C**\u5FC5\u987B\u91CD\u8DD1** `check` \u2014\u2014 \u672C\u4ED3\u7684\u6559\u8BAD\u662F\"\u68C0\u67E5\u6CA1\u8DD1\"\u548C\"\u68C0\u67E5\u901A\u8FC7\"\u5728\u8F93\u51FA\u4E0A\u5FC5\u987B\u5206\u5F97\u5F00\uFF1B\n`review` \u51FA\u7684\u662F**\u95EE\u9898\u6E05\u5355**\uFF08\u534A\u673A\u68B0\u3001\u8981\u4EBA\u56DE\u7B54\uFF09\uFF0C**\u4E0D\u662F**\u901A\u8FC7/\u4E0D\u901A\u8FC7\u3002\n";
8
8
  export declare function createSkillCreatorTool(): import("@deepseek-ai/dsh-tools").ToolDefinition;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.54.0",
3
+ "version": "1.56.0",
4
4
  "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:13 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/ontology/handyman/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.7-rc.1。",
5
5
  "license": "MIT",
6
6
  "repository": {