ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

diagram-design 的 SKILL.md 字节上限与触发型 description:ADR 0004 决策全解析

diagram-design 的 SKILL.md 字节上限与触发型 description:ADR 0004 决策全解析 diagram-design 的 SKILL.md 字节上限与触发型 descriptionADR 0004 决策全解析【免费下载链接】diagram-design38 editorial diagram types for Claude Code, Codex, and Pi. Self-contained HTML SVG. No shadows. No Mermaid slop.项目地址: https://gitcode.com/GitHub_Trending/di/diagram-design本篇文章围绕 diagram-design 仓库的架构决策记录 ADR 0004SKILL.md byte cap and the trigger-rich description展开讲清楚一个面向 Claude Code、Codex、Pi 等 Agent 的绘图技能skill为什么必须严格控制SKILL.md的体积以及为什么 frontmatter 里的description必须穷举全部视觉类型名称。读完本文你将掌握该决策的来龙去脉、两条强制规则的源码级实现、CI 中的落地方式以及新增一种视觉类型时整个仓库的联动约束。一、背景SKILL.md 每次调用都进入 Agent 上下文diagram-design 是一个以 38/39 种编辑级视觉类型为核心的绘图技能仓库其行为主体是位于 skills/diagram-design/SKILL.md 的技能定义文件。ADR 0004 开篇就点明了它的核心约束SKILL.mdloads into an agents context on every skill invocation, so it must stay lean; a byte cap keeps growth honest.也就是说AgentClaude Code、Codex、Pi 等在每一次调用该技能时都会把整个SKILL.md载入其上下文窗口。这意味着文件的每一个字节都在消耗 Agent 的上下文预算也都在影响技能被调用的准确率与后续生成质量。因此对SKILL.md设置字节上限本质上是给“内容增长”安装一个刹车——让维护者在扩容时不得不思考取舍而不是无节制地堆积正文。从当前仓库的实际状态看这一约束是真实存在的SKILL.md目前的字节数为39,535 字节wc -c实测距离上限 40,000 字节仅剩约 465 字节的余量属于在“贴着红线运行”的典型状态。二、问题v2.3 的 35KB 上限如何差点毁掉技能被发现的能力ADR 0004 记录了一次真实的回归事故这也是整份决策的导火索v2.3 版本曾把上限设定为35,000 字节为了把体积压回上限以内维护者删减了 frontmatter 中的description其代价是删掉了全部 27 个视觉类型名称而description恰恰是 Agent 在决定是否加载该技能之前唯一能看到的文本。ADR 原文对此的定性非常尖锐The description is the only text an agent seesbeforedeciding to load the skill: removing flowchart, Gantt, org chart from it removes the lexical hooks that make make me a flowchart invoke the skill at all.关键词是lexical hooks词法钩子。Agent 的技能路由机制本质上是一个文本匹配过程当用户说“帮我画一个流程图 / make me a Gantt chart”时Agent 会扫描各技能的description看谁的文本里出现了与用户请求重叠的词汇。如果description里没有 flowchart、Gantt、org chart 这些词Agent 就无法把这些用户意图路由到 diagram-design技能等于“存在但永远不被发现”。这也揭示了本决策的第一层设计哲学路由表面积routing surface优先于正文修辞body prose。技能要能被正确唤起靠的不是正文写得有多详尽而是 description 里是否覆盖了足够多的用户会使用的自然语言词汇。三、决策两条按优先级排序的强制规则ADR 0004 给出的解决方案是两条规则并明确标注了优先级顺序优先级规则强制方核心内容1description 必须穷举全部视觉类型scripts/verify-docs-sync.pydescription 必须包含选择表中每一个视觉类型的名称外加导入格式与主要特性词汇2MAX_SKILL_BYTES 40,000scripts/verify-semantic-motion.py文件接近上限时只能削减正文或把细节迁移到references/绝不能动 description规则 1 的措辞值得逐字解读The frontmatterdescriptionmust name every visual type in the selection table (enforced byscripts/verify-docs-sync.py) plus the import formats and major feature vocabulary. Routing surface is never traded for body prose.selection table选择表即 SKILL.md 中的### Visual-type guide (39)表格当前收录了 39 种视觉类型import formats导入格式即.drawio/.drawio.png/.drawio.svg与 Mermaid.mmd等源文件格式major feature vocabulary主要特性词汇如 semantic patterns、callouts、accessible motion、sketchy/hand-drawn styling、brand tokens 等描述性词汇。规则 2 则明确了“如果体积超标砍哪里”的取舍原则When the file approaches the cap, cut body prose or move detail intoreferences/— never the description.这条规则与仓库的整体架构高度契合SKILL.md 只保留路由与调度骨架而把 type-architecture.md、type-flowchart.md 等 30 余份类型参考文档、semantic-patterns.md、style-guide.md 等设计系统文档全部放在references/目录下按需加载正是“正文瘦身、细节外置”这一决策的落地形态。四、源码级实现一verify-docs-sync.py 如何强制 description 穷举类型规则 1 的强制实现是 scripts/verify-docs-sync.py其 docstring 开篇就点明了动机The SKILL.md frontmatter description is the only text an agent sees before deciding to load the skill — every visual type in the selection table must keep a lexical hook there.4.1 核心检查链路该脚本的check_description()函数verify-docs-sync.py完成三步验证解析 SKILL.md 的 frontmatter提取description字段frontmatter_description()L94-L99用正则从### Visual-type guide到Rules of thumb之间提取选择表中的全部类型名selection_table_types()L102-L108并断言数量必须等于VISUAL_TYPE_COUNT 39对每个类型名做归一化后逐一检查其词法钩子是否存在于 description 中缺失任何一个都会报错description lost the lexical hook for type org chart (expected org chart in the SKILL.md frontmatter description)4.2 别名映射表格名与描述词汇的差异处理值得注意的是脚本中的DESCRIPTION_ALIASESL44-L49DESCRIPTION_ALIASES { bar chart: bar, line chart: line, scatter plot: scatter, }这是因为选择表中的类型名如 bar chart与 description 中的自然语言词汇bar存在细微差异。如果直接做字符串包含判断bar chart 会要求 description 中出现 bar chart 四个字而过长的 description 更占字节——所以脚本允许通过别名把表格名映射为更精简的描述词汇在“保证词法钩子存在”与“控制字节数”之间取得平衡。4.3 归一化策略normalized()函数L88-L91将所有文本转为小写、压缩空白、统一斜杠格式确保 Radar / Spider 与 radar/spider 这类写法差异不会造成误报或漏报。五、源码级实现二description 的连锁同步义务ADR 0004 的一个重要推论是description 不仅是路由表面它还会扩散到仓库的其他位置因此 verify-docs-sync.py 对多处“表面”施加了同一条词法钩子义务。5.1 插件 manifest 必须逐字重复 descriptionMANIFEST_DESCRIPTIONSL384-L389列出了四个 manifest 文件.claude-plugin/plugin.jsondescription.claude-plugin/marketplace.jsondescription.codex-plugin/plugin.jsondescription、longDescription.factory-plugin/plugin.jsondescriptioncheck_manifest_descriptions()L409-L434会递归地在这些 JSON 文档中查找对应键并断言其中的文本与 SKILL.md 的 description 一样包含全部 39 个类型的词法钩子。脚本注释给出了这样做的理由The plugin manifests repeat the SKILL.md description verbatim. They are the text a user readsbefore installing, so by ADR 0004s own argument they need every types lexical hook too - and nothing else notices when they drift, because they are four separate copies of one sentence.对照实际文件可以验证当前 .claude-plugin/plugin.json 中的description与 SKILL.md frontmatter 的 description 确实逐字一致完整列出了 architecture、flowchart、sequence、Gantt、org chart 等全部类型及 .drawio/Mermaid 导入能力。5.2 导入命令不得硬编码类型数量check_type_counts()L318-L333针对 commands/import-drawio.md 与 commands/import-mermaid.md 两个导入命令文件禁止其中出现“one of the 27”“28 visual types”“28 types of visual diagrams”这类硬编码的数字。脚本注释记录了一段真实历史A command that spells the type count out has to be edited by every PR that adds a type, and is the one file such a PR has no reason to open. Both import commands were left at 27 while the selection table moved on.两个导入命令曾在选择表演进到更多类型后仍然停留在“27”这个过时数字。解决方式是让命令指向 SKILL.md 的选择表本身而不是复述一个会过期的数量。正则HARDCODED_COUNT_RE既匹配one of the 27这类裸计数也匹配“数字 形容词 visual/diagram types”的多种句式同时特意放行“accepts 2 file types”这类与视觉类型无关的数量避免误伤。5.3 回归测试test-verify-docs-sync.pyscripts/test-verify-docs-sync.py 是上述检查器的回归测试覆盖了多类漂移场景失效的引用链接、越权路径references/../secrets.md、URL 编码的 Windows 遍历%2e%2e%5c、缺失的打包运行时文件、路由表面commands/prompts指向过时参考、Factory Droid 安装命令顺序颠倒、硬编码类型数量含换行折行后的变体等。它证明了这套检查不是一次性脚本而是被当作持续可验证的契约来维护的。六、源码级实现三verify-semantic-motion.py 与 40,000 字节上限规则 2 的强制实现位于 scripts/verify-semantic-motion.pyMAX_SKILL_BYTES 40_000其verify_markdown()函数中的检查逻辑L183-L191skill_bytes SKILL.read_bytes() ... if len(skill_bytes) MAX_SKILL_BYTES: errors.append( fSKILL.md exceeds {MAX_SKILL_BYTES} bytes: {len(skill_bytes)} bytes )注意这里使用的是read_bytes()得到的原始字节数raw bytes而不是解码后的字符数——这直接呼应了 ADR 0004 中“cap is measured on raw bytes”的表述。也正因如此行尾符CRLF vs LF会直接影响计数的结果进而引出了下一节的 CI 配置细节。同一个脚本还顺带验证了语义模式路由必须先于视觉类型选择表semantic-patterns.md的链接位置必须位于### Visual-type guide (39)之前、39 行视觉类型表必须完整保留、7 个语义模式各自的必需字段、动画模式none/reveal/step/loop与动效原语的存在性等契约。七、CI 落地字节计数与 core.autocrlffalse 的关系ADR 0004 的 Consequences 部分明确指出The cap is measured on raw bytes withcore.autocrlffalsepinned in CI checkout; Windows contributors should keep LF endings forSKILL.md.这一约束在 .github/workflows/ci.yml 中有对应实现。validatejob 的 checkout 步骤L86-L94通过 Git 环境变量固定了行尾转换行为- name: Checkout repository uses: actions/checkoutv7 env: GIT_CONFIG_COUNT: 1 GIT_CONFIG_KEY_0: core.autocrlf GIT_CONFIG_VALUE_0: false with: persist-credentials: false同样的core.autocrlffalse配置也出现在plugin-packagejob 中L25-L28。原因很直观如果 CI 在检出时把 LF 自动转成 CRLF或反之那么“SKILL.md 是否超过 40,000 字节”的判定结果就会取决于运行平台同一个提交在 Windows 与 Linux 上可能得到不同的结论。固定为false后CI 中的字节数就是仓库中真实存储的字节数检查结果可复现。对 Windows 贡献者的实际含义是编辑 skills/diagram-design/SKILL.md 时应保持 LF 行尾。Git 配置了core.autocrlftrue的机器在 checkout 时通常会把 LF 转成 CRLF本地可读性没问题但提交时一般会转回 LF真正需要警惕的是编辑器直接以 CRLF 保存文件、或core.autocrlf设置不一致导致的字节膨胀——每个 CRLF 行尾比 LF 多 1 字节对于仅剩约 465 字节余量的文件来说这是不可忽视的差异。此外CI 的validatejob 中有两个与此 ADR 直接相关的步骤L105-L113- name: Verify semantic pattern documentation run: python scripts/verify-semantic-motion.py --markdown-only - name: Verify animated example structure run: python scripts/verify-semantic-motion.py --example-only以及 docs 同步检查步骤L185-L191- name: Verify docs and routing sync run: | python scripts/verify-docs-sync.py python scripts/test-verify-docs-sync.py这些步骤在 push 到 main 与 PR 时都会运行workflow 的on触发器并且矩阵覆盖 ubuntu / windows / macos 三平台 × Python 3.11 / 3.12——也就是说任何绕过 description 词法钩子或撑大 SKILL.md 字节数的改动都会在合并前被 CI 拦截。八、后果与工作流约束新增一种视觉类型意味着什么ADR 0004 记录了三条 Consequences其中第一条最反直觉、也最体现“by design”的设计意图Adding a visual type requires touching the description; CI fails otherwise, by design.在大多数项目里“新增一种类型”只需要改选择表和类型参考文档但在 diagram-design 中新增类型必然同时修改 description否则 CI 直接失败。这并非缺陷而是有意为之description 是技能的“发现层”一个没有被 description 命名的新类型Agent 永远无法在用户提出相关需求时唤起它——那么它对这个 Agent 技能来说就是不存在的。把“改名 description”变成硬性前置条件等于从机制上杜绝了“功能存在但不可发现”的静默失效。综合前文新增一种视觉类型时开发者需要联动触达的检查点包括检查点强制方内容SKILL.md 选择表verify-semantic-motion.py### Visual-type guide (39)必须保持 39 行SKILL.md frontmatter descriptionverify-docs-sync.py必须新增该类型的词法钩子SKILL.md 字节数verify-semantic-motion.pyread_bytes()后不得超过 40,000 字节插件 manifest4 个文件verify-docs-sync.pydescription/longDescription 同样必须包含新类型词法钩子导入命令文档verify-docs-sync.py不得出现硬编码的类型数量数字行尾符.github/workflows/ci.ymlSKILL.md 需保持 LFCI 固定core.autocrlffalse其中第二、四条检查对应着 ADR 文档没有展开、但源码中真实存在的两个细节description 的复制扩散义务manifest 是 description 的四份副本与数量路由义务导入命令指向 SKILL.md 选择表而非写死数字。这两条都是 ADR 决策在实现层被进一步深化后的产物阅读 verify-docs-sync.py 的 docstring 可以确认这正是其“Ten drift classes, each of which has shipped before”的由来。九、为什么这套机制对 Agent 技能仓库尤其重要将 ADR 0004 放回 diagram-design 的整体架构中看可以提炼出三层普适经验发现层与执行层分离。SKILL.md 是发现层负责被正确路由references/是执行层负责具体绘制规则。ADR 0004 用字节上限强制了这种分离——细节永远可以外置到 references但路由词汇绝不能从 description 中消失。用 CI 把架构决策变成不可绕过的契约。字节上限、词法钩子、manifest 同步、数量路由每一项都有独立的 Python 校验脚本与回归测试并在三平台矩阵 CI 中强制执行。决策不是写在文档里供人自觉遵守而是变成了合并代码的前置条件。字节预算即设计预算。当前 SKILL.md 39,535 字节、距上限不足 500 字节的状态本身就是一种信号任何新的正文内容都必须先回答“值不值得挤占 description 之外的余量”这迫使维护者对每个新增段落做价值判断从而让整个技能文件长期保持精简。十、结语ADR 0004 表面上是关于“一个 Markdown 文件多大合适”的琐碎决策实质上回答了一个 Agent 技能仓库最核心的问题如何保证技能既能被准确唤起又不至于在每次调用时过度消耗 Agent 上下文。它的答案是两条硬规则——description 穷举全部类型词法钩子由 verify-docs-sync.py 强制、SKILL.md 不超过 40,000 原始字节由 verify-semantic-motion.py 强制——再配合 CI 中固定的core.autocrlffalse与三平台矩阵验证把“路由优先、正文瘦身”的设计哲学固化成了每一次提交都必须通过的技术门槛。对于任何希望为 Agent 生态编写可被稳定发现、可长期维护的技能文件SKILL.md / plugin manifest的开发者这份 ADR 及其源码实现都是一个值得对照参考的完整范式从一次 27 个类型名被删的事故出发最终演化为一套覆盖路由、字节、同步、打包与行尾符的自动校验体系。【免费下载链接】diagram-design38 editorial diagram types for Claude Code, Codex, and Pi. Self-contained HTML SVG. No shadows. No Mermaid slop.项目地址: https://gitcode.com/GitHub_Trending/di/diagram-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表