Ponytail /ponytail-audit 全仓库过度设计审计:五种标签、输出契约与边界规则
Ponytail 是一款让 AI Agent 以"最懒资深工程师"标准写代码的工具集,其中的 ponytail-audit 技能负责对整个代码仓库(而非当前 diff)做一次过度工程审计,产出一份按"能砍多少"排序的删除/简化清单。本文基于仓库中的技能定义 .openclaw/skills/ponytail-audit/SKILL.md 展开,完整讲解其元数据、五类审计标签、排查清单(Hunt)、单行输出契约、作用边界,并结合仓库源码说明该技能如何在 OpenClaw、Claude Code、OpenCode、pi 等不同 Agent 宿主中落地与一致性校验,读完你可以准确理解该技能的输入输出协议,并在自己的 Agent 工作流中正确调用它。
1. ponytail-audit 的定位:ponytail-review 的全仓库版本
技能正文第一句就交代了它与 ponytail-review 的关系:
ponytail-review, repo-wide. Scan the whole tree instead of a diff. Rank findings biggest cut first.
即:ponytail-review 只审查当前 diff,而 ponytail-audit 扫描整棵代码树,并把发现按"最大削减量优先"排序。两者的标签体系完全一致(技能文档明确写有 "Same as ponytail-review"),核心差异在扫描范围和输出定位方式。这个对照可以直接从仓库中两份技能定义确认:
- 全仓库审计版:.openclaw/skills/ponytail-audit/SKILL.md(规范化源文件为 skills/ponytail-audit/SKILL.md)
- diff 审查版:skills/ponytail-review/SKILL.md
两者共同遵循 Ponytail 的核心哲学——"最好的代码是你没写的代码"。项目 README 中的决策阶梯(写代码前先停下来,停在第一个成立的 rung 上)是理解审计标签体系的钥匙:
1. Does this need to exist? → no: skip it (YAGNI)
2. Already in this codebase? → reuse it, don't rewrite
3. Stdlib does it? → use it
4. Native platform feature? → use it
5. Installed dependency? → use it
6. One line? → one line
7. Only then: the minimum that works
ponytail-audit 的每一项 Hunt 规则,本质上就是把这架阶梯反过来用:第 2 档对应 delete/复用,第 3 档对应 stdlib,第 4 档对应 native,第 1、7 档对应 yagni,"更短写法"对应 shrink。
2. 技能元数据:front-matter 与 OpenClaw 适配约束
.openclaw/skills/ 下这份技能文件带有 YAML front-matter:
---
name: ponytail-audit
description: "Audit the whole repo for over-engineering. A ranked list of what to delete, simplify, or replace with stdlib or native features."
homepage: https://github.com/DietrichGebert/ponytail
license: MIT
---
注意它与规范化源文件 skills/ponytail-audit/SKILL.md 在 description 上的差异:
| 位置 | description 形态 |
|---|---|
| skills/ponytail-audit/SKILL.md(规范化源) | 多行折叠写法(> 语法),含完整触发语:"audit this codebase"、"find bloat"、"/ponytail-audit" 等 |
| .openclaw/skills/ponytail-audit/SKILL.md(OpenClaw 发行版) | 压缩成一句话,并增加 homepage、license 字段 |
这不是人工漂移,而是生成流水线刻意为之。README 的 Development 章节说明:.openclaw/skills/ 包由 skills/ 经构建脚本生成,改动技能后需重新生成,测试套件会因过期而失败。仓库中对应的保障机制有两条:
- scripts/build-openclaw-skills.js —— 生成器,负责把规范化技能正文与面向 OpenClaw 的单行 description 拼装成最终文件;
- tests/openclaw-skills.test.js —— 对每个技能做三项断言:
- 磁盘上的
.openclaw/skills/<name>/SKILL.md与render(name)逐字节一致,"stale" 即失败; - 文件正文必须以
skills/<name>的正文逐字结尾("body drifted" 检测); - description 必须是单行且不超过 160 字符(OpenClaw 的单行 <160 规则)。
- 磁盘上的
因此引用 .openclaw/skills/ponytail-audit/SKILL.md 时应理解它是一份生成产物:正文与 skills/ponytail-audit/SKILL.md 相同,差异只在 front-matter。这也解释了为什么 OpenClaw 版本把冗长的触发语列表删掉——触发语在 OpenClaw 中不是 description 的职责。
3. 五种审计标签(Tags)
标签体系是 ponytail-audit 的核心协议,与 ponytail-review 完全相同,共五种:
| 标签 | 适用对象 | 替代物要求 |
|---|---|---|
delete: |
死代码(dead code)、没人用的灵活性(unused flexibility)、投机性功能(speculative feature) | 无(Replacement: nothing),直接删 |
stdlib: |
手写的、标准库本来就有(hand-rolled)的功能 | 必须点名标准库的具体函数 |
native: |
依赖或代码在做平台/宿主环境本来就会做的事 | 必须点名平台的具体特性 |
yagni: |
只有一个实现的抽象、没人设置的配置项、只有一个调用方的分层 | 内联/塌缩,直到真正出现第二个需求 |
shrink: |
同一逻辑可用更少行数表达 | 必须展示更短的写法 |
从标签定义可以看出两个硬性要求:stdlib: 和 native: 不能只说"这可以简化",必须指名道姓(name the function / name the feature),这让审计结果可直接执行;shrink: 必须"展示更短形式"(show the shorter form),避免空洞建议。这些约束在 ponytail-review 的技能示例里体现得很具体,例如:
L4: native: moment.js imported for one format call. Intl.DateTimeFormat, 0 deps.(点名平台 API)L30-44: shrink: manual loop builds dict. dict(zip(keys, values)), 1 line.(给出更短形式)
审计场景把这些示例中的行号定位换成文件路径即可。
4. Hunt:审计时到底找什么
技能文档的 Hunt 小节给出了一份七项排查清单,这是 ponytail-audit 区别于泛泛"代码评审"的实质内容:
- 标准库或平台已内置的依赖 —— 对应
stdlib:/native:,即"装了个包只是用它的一两个标准函数"; - 单实现接口(single-implementation interfaces) —— 只有唯一实现体的抽象接口,对应
yagni:; - 只有一个产品的工厂(factories with one product) —— 工厂模式退化成一个
new; - 只负责转发的包装层(wrappers that only delegate) —— 调用 A 的 B 方法只是原样转发给 A,对应
delete:; - 只导出一个东西的文件(files exporting one thing) —— 过度拆分的模块边界;
- 死开关与死配置(dead flags and config) —— 没人设的配置项、永远为假的 feature flag;
- 手搓标准库(hand-rolled stdlib) —— 自己重写
groupBy、debounce、URL 解析等标准能力,对应stdlib:。
这七项与 README 中 Ponytail 的"阶梯"逐档对应,也解释了为什么审计是"按最大削减量排序"——delete 和 stdlib/native 通常能砍掉整块代码与整个依赖,而 shrink 只省几行,排序因此天然由"可删除的代码量 + 依赖数"决定。
5. 输出契约:每发现一行,按削减量排序
技能对输出格式有非常严格的约束,这也是该技能可以被脚本化消费的原因:
- 每条发现一行,格式为:
<tag> <what to cut>. <replacement>. [path] - 排序规则:biggest cut first(最大的削减排最前)
- 结尾必须是净收益统计:
net: -<N> lines, -<M> deps possible. - 无可削减时固定输出:
Lean already. Ship.
与 ponytail-review 的输出对照可以看出演化:review 版要求 L<line>: <tag> ...(diff 行号),且净收益只统计行数(net: -<N> lines possible.);audit 版把定位改为 [path](仓库级没有 diff 行号),并把依赖数也纳入净收益(-<M> deps),因为整库审计时"能删掉几个依赖"是仅次于行数的第二价值指标。
按该格式,一份审计输出的典型形态如下(示意,用于说明格式而非真实数据):
stdlib: 42-line dateDiff util. Date.prototype diff via Intl.RelativeTimeFormat, 3 lines. [src/utils/diff.ts]
native: dayjs bundled for one format call. Intl.DateTimeFormat, -1 dep. [src/utils/format.js]
delete: retry wrapper around an idempotent local call. Nothing replaces it. [src/api/call.ts]
yagni: AbstractStorage with one implementation. Inline it until a second exists. [src/storage/base.ts]
shrink: manual loop builds dict. dict(zip(keys, values)), 1 line. [src/utils/map.py]
net: -180 lines, -2 deps possible.
6. 边界(Boundaries):审计只找过度设计,不找 Bug
技能文档的 Boundaries 小节划定了四条硬边界,理解它们能避免对该技能的误用:
- 范围仅限过度工程与复杂度。正确性缺陷(correctness bugs)、安全漏洞(security holes)、性能问题(performance)明确不在范围内,应路由到常规 review 流程处理;
- 只列清单,不落地修改(Lists findings, applies nothing)——它是一份报告,不是一个自动重构器;
- 一次性(One-shot)——产出报告后即结束,不进入持续审计模式;
- 退出短语——"stop ponytail-audit" 或 "normal mode" 让 Agent 退出该模式,回到常规审查风格。
对照 skills/ponytail-review/SKILL.md 可以看到边界体系是成对的:review 版额外强调"单个冒烟测试或 assert 自检是 ponytail 的最低标准而非 bloat,绝不标记为删除"——即审计/审查模式有"最小保护"底线,防止 Agent 把必要的自检代码也砍掉。这与项目 README 的总原则一致:"write only what the task needs, and never cut validation, error handling, security, or accessibility."
7. 运行方式:OpenClaw 及其他宿主
OpenClaw 安装
README 给出两种路径:
clawhub install ponytail-audit
六个技能(review、audit、debt、gain、help、ponytail 本体)均可用同样方式安装;不走 ClawHub 时,把 .openclaw/skills/ponytail-audit 目录手动复制到 ~/.openclaw/skills/ 即可。安装后 OpenClaw 会在编码任务上应用它,并暴露 /ponytail 命令族。
其他宿主的等价入口
/ponytail-audit 命令在各宿主中的适配文件都能在仓库中验证到,且由测试保证不缺失:
| 宿主 | 适配文件 / 机制 |
|---|---|
| Claude Code / Gemini CLI | commands/ponytail-audit.toml(TOML 单行 prompt,Gemini CLI 复用该目录) |
| OpenCode | .opencode/command/ponytail-audit.md |
| pi agent | pi-extension/index.js 中 pi.registerCommand("ponytail-audit", ...),handler 转发 /skill:ponytail-audit |
| 通用规则注入 | AGENTS.md 被多宿主自动加载,规则在无插件时也生效 |
其中 commands/ponytail-audit.toml 的内容是技能正文的"压缩 prompt 版",把标签、输出格式、排序规则与 "Lean already. Ship." 兜底全部塞进一段指令:
description = "Audit the whole repo for over-engineering, what can be deleted"
prompt = "Audit the entire repository for over-engineering only, not correctness. Scan the whole tree, not a diff. One line per finding, ranked biggest cut first: <tag> <what to cut>. <replacement>. [path]. Tags: delete (dead code/speculative feature), stdlib (reinvented standard library), native (dependency doing what the platform does), yagni (abstraction with one implementation), shrink (same logic, fewer lines). End with the net lines and dependencies removable. If nothing to cut: 'Lean already. Ship.'"
值得注意的是 tests/commands.test.js 的守卫逻辑:它从 pi-extension/index.js 中解析出所有 registerCommand 注册名,逐一断言 commands/<name>.toml 与 .opencode/command/<name>.md 存在——"注册了命令却没有适配文件"会导致测试失败。从源码结构看,这套测试意味着新增/删除技能时,.openclaw/skills/、skills/、commands/、.opencode/command/、pi 扩展五处会被迫同步,这解释了本仓库技能定义在多个目录下"看似重复"的原因:它们是同一协议的不同宿主投影,由生成器与测试锁定一致。
8. 实践建议:什么时候用 audit,什么时候用 review
基于两份技能文档的差异,可以在工作流中做如下分工:
- 提交前看 diff:用
ponytail-review,输出带行号的删除清单,聚焦本次改动是否引入过度设计; - 接手仓库 / 技术债盘点:用
ponytail-audit,整库扫描,按削减量排序,结尾给出-<N> lines, -<M> deps的总账; - 审计之后:由于 audit 只列不修(applies nothing),落地仍需常规提交流程逐条执行,且正确性、安全、性能问题应另行送常规 review——这正是 Boundaries 要求"route them to a normal review pass"的原因。
9. 小结
ponytail-audit 把"仓库里能删什么"变成了一份有严格协议的报告:五种标签(delete / stdlib / native / yagni / shrink)界定发现类型,七项 Hunt 清单界定扫描目标,单行格式 + 最大削减优先 + net: -<N> lines, -<M> deps possible. 界定输出,Boundaries 则把正确性、安全、性能明确排除在外。仓库中 skills/ponytail-audit/SKILL.md 为规范化源,.openclaw/skills/ponytail-audit/SKILL.md 为生成产物,commands/ponytail-audit.toml 与 .opencode/command/ponytail-audit.md 为命令投影,tests/openclaw-skills.test.js 与 tests/commands.test.js 负责在 CI 层面锁住各投影之间的一致性。理解这套协议后,你可以在任何支持技能系统的 Agent 宿主中触发整库过度设计审计,并以可预测的格式消费其结果。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00