diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index f00d442..0ee1543 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "llmdoc", "source": "./", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", - "version": "3.5.0" + "version": "3.5.1" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index f9adaf0..456a0f1 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "llmdoc", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", - "version": "3.5.0", + "version": "3.5.1", "author": { "name": "DJJ & Danniel" } diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 616bd91..6500572 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "llmdoc", - "version": "3.5.0", + "version": "3.5.1", "description": "Persistent engineering context powered by the llmdoc CLI and progressive MDX knowledge retrieval", "skills": "./.agents/skills/" } diff --git a/.github/workflows/codex-plugin-scanner.yml b/.github/workflows/codex-plugin-scanner.yml index 35af4f4..b236c73 100644 --- a/.github/workflows/codex-plugin-scanner.yml +++ b/.github/workflows/codex-plugin-scanner.yml @@ -34,6 +34,9 @@ jobs: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2 + - name: Install scanner dependencies + run: npm ci --ignore-scripts + - name: Run scanner # 上游 hashgraph-online/codex-plugin-scanner 迁库后暂无可用 action; # 用仓库内建校验覆盖 manifest schema、skills frontmatter 与 hooks 约定, diff --git a/cli/package-lock.json b/cli/package-lock.json index a964d96..085d5d3 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tokenroll/llmdoc", - "version": "3.5.0", + "version": "3.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenroll/llmdoc", - "version": "3.5.0", + "version": "3.5.1", "dependencies": { "ajv": "^8.17.1", "commander": "^13.1.0", diff --git a/cli/package.json b/cli/package.json index 21de430..ee94ca1 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@tokenroll/llmdoc", - "version": "3.5.0", + "version": "3.5.1", "description": "V3 runtime CLI for llmdoc repositories", "homepage": "https://github.com/TokenRollAI/llmdoc", "repository": { diff --git a/llmdoc/meta.json b/llmdoc/meta.json index ca7525a..ea7f86a 100644 --- a/llmdoc/meta.json +++ b/llmdoc/meta.json @@ -6,7 +6,7 @@ }, "documents": { "architecture.mdx": { - "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" + "validatedRevision": "0157d17e0cca2eb0ed0aaf20da41b80035be3a2e" }, "cli-runtime/state-and-validation.mdx": { "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" @@ -15,10 +15,10 @@ "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" }, "plugin-packaging/claude-and-codex.mdx": { - "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" + "validatedRevision": "0157d17e0cca2eb0ed0aaf20da41b80035be3a2e" }, "plugin-packaging/development-and-release.mdx": { - "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" + "validatedRevision": "832bcf943c10528b60f01a02a7d8ce607ea44699" }, "workflows/init-and-update.mdx": { "validatedRevision": "61ef5822ec305f61ebf41bb826e143a889c31e5e" diff --git a/llmdoc/plugin-packaging/claude-and-codex.mdx b/llmdoc/plugin-packaging/claude-and-codex.mdx index 128d212..130e977 100644 --- a/llmdoc/plugin-packaging/claude-and-codex.mdx +++ b/llmdoc/plugin-packaging/claude-and-codex.mdx @@ -30,6 +30,6 @@ Claude 根插件是手工维护的 canonical surface:skills 定义 Retrieval/R 转换必须在临时副本生成后替换式同步,因为生成器不保证清除陈旧输出。Codex 角色文本不手工维护;宿主特有 front matter/TOML 可以不同,实际 skill 与 agent 指令正文必须与 Claude canonical 一致。 -`scripts/check-codex-surface.mjs` 在 CI 中机械校验版本/marketplace 身份、五个 skill 与三个 agent 的正文一致性、Reflection Gate 约束和 hook 调用。人工 checklist 只补宿主 UI policy 与信任模型等无法从正文等价判断的部分。 +`scripts/check-codex-surface.mjs` 在 CI 中机械校验版本/marketplace 身份、五个 skill 与三个 agent 的正文一致性、Reflection Gate 约束和 hook 调用。它还分别遍历 `skills/` 与 `.agents/skills/`,用 `gray-matter` 解析每份 `SKILL.md` 的 YAML front matter,并要求 `name`、`description` 是非空字符串;这是两侧各自的语法门槛,不替代跨宿主正文 parity。人工 checklist 只补宿主 UI policy 与信任模型等无法从正文等价判断的部分。 hooks 位于共享插件根,一份配置供两种宿主使用;它们保持 fail-open、只读,且由安装宿主按自己的信任模型启用。 diff --git a/llmdoc/plugin-packaging/development-and-release.mdx b/llmdoc/plugin-packaging/development-and-release.mdx index f8efc9c..016fedc 100644 --- a/llmdoc/plugin-packaging/development-and-release.mdx +++ b/llmdoc/plugin-packaging/development-and-release.mdx @@ -16,7 +16,7 @@ code: ## 消费与开发边界 -公开产物是 `@tokenroll/llmdoc` CLI;仓库根 package 只是私有开发工作区。消费项目通过外部 npx/global 安装使用 CLI,不把 llmdoc 写进自己的依赖和 lockfile。 +公开产物是 `@tokenroll/llmdoc` CLI;仓库根 package 只是私有开发工作区。消费项目通过外部 npx/global 安装使用 CLI,不把 llmdoc 写进自己的依赖和 lockfile。根工作区直接声明的 `gray-matter` 只供 `scripts/check-codex-surface.mjs` 解析 skill front matter,不是消费方依赖,也没有为 CLI 新增 runtime 依赖。 ## 非平凡编辑前先同步 diff --git a/package-lock.json b/package-lock.json index 906a212..4d4c89b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.0", + "version": "3.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.0", + "version": "3.5.1", "devDependencies": { - "@tokenroll/llmdoc": "file:cli" + "@tokenroll/llmdoc": "file:cli", + "gray-matter": "^4.0.3" }, "engines": { "node": ">=18" @@ -16,7 +17,7 @@ }, "cli": { "name": "@tokenroll/llmdoc", - "version": "3.5.0", + "version": "3.5.1", "dev": true, "dependencies": { "ajv": "^8.17.1", diff --git a/package.json b/package.json index 53161c5..c8a4dd3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tokenroll/llmdoc-repository", - "version": "3.5.0", + "version": "3.5.1", "private": true, "description": "Development workspace for the llmdoc V3 CLI and plugin surfaces", "scripts": { @@ -12,7 +12,8 @@ "check:prompts": "node scripts/check-prompt-budget.mjs" }, "devDependencies": { - "@tokenroll/llmdoc": "file:cli" + "@tokenroll/llmdoc": "file:cli", + "gray-matter": "^4.0.3" }, "overrides": { "vite": "6.4.3" diff --git a/scripts/check-codex-surface.mjs b/scripts/check-codex-surface.mjs index 9fef109..5001076 100644 --- a/scripts/check-codex-surface.mjs +++ b/scripts/check-codex-surface.mjs @@ -4,6 +4,7 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import matter from "gray-matter"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const errors = []; @@ -78,22 +79,47 @@ for (const [label, version] of versionSurfaces) { } } -// 3) Codex skills:每个 SKILL.md 有 frontmatter name + description -const skillsRoot = path.join(root, ".agents/skills"); -if (fs.existsSync(skillsRoot)) { - for (const dir of fs.readdirSync(skillsRoot)) { - const skillFile = path.join(skillsRoot, dir, "SKILL.md"); +// 3) Claude/Codex skills:每个 SKILL.md 的 YAML frontmatter 可解析且有 name + description +function validateSkills(skillsDir) { + const skillsRoot = path.join(root, skillsDir); + if (!fs.existsSync(skillsRoot)) return; + + for (const entry of fs.readdirSync(skillsRoot, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + + const rel = path.posix.join(skillsDir, entry.name, "SKILL.md"); + const skillFile = path.join(root, rel); if (!fs.existsSync(skillFile)) { - errors.push(`.agents/skills/${dir}: 缺少 SKILL.md`); + errors.push(`${path.posix.join(skillsDir, entry.name)}: 缺少 SKILL.md`); + continue; + } + + const source = fs.readFileSync(skillFile, "utf8"); + if (!source.startsWith("---\n") && !source.startsWith("---\r\n")) { + errors.push(`${rel}: 缺少 frontmatter`); + continue; + } + + let data; + try { + data = matter(source).data; + } catch (error) { + errors.push(`${rel}: frontmatter YAML 无法解析 — ${error.message}`); continue; } - const head = fs.readFileSync(skillFile, "utf8").split("\n---")[0]; - if (!/^---/.test(head)) errors.push(`.agents/skills/${dir}/SKILL.md: 缺少 frontmatter`); - if (!/\bname:/.test(head)) errors.push(`.agents/skills/${dir}/SKILL.md: frontmatter 缺少 name`); - if (!/\bdescription:/.test(head)) errors.push(`.agents/skills/${dir}/SKILL.md: frontmatter 缺少 description`); + + if (typeof data.name !== "string" || data.name.trim() === "") { + errors.push(`${rel}: frontmatter 缺少有效 name`); + } + if (typeof data.description !== "string" || data.description.trim() === "") { + errors.push(`${rel}: frontmatter 缺少有效 description`); + } } } +validateSkills("skills"); +validateSkills(".agents/skills"); + // 4) 三个角色跨宿主齐备;Reflector 只能写临时候选,不恢复 tracked reflection 树。 for (const agent of ["investigator", "reflector", "recorder"]) { for (const rel of [`agents/${agent}.md`, `.codex/agents/${agent}.toml`]) {