首页
/ Ponytail 规则集详解:让 AI Agent 以"懒资深工程师"方式写代码的 Kiro Steering 规则

Ponytail 规则集详解:让 AI Agent 以"懒资深工程师"方式写代码的 Kiro Steering 规则

2026-09-03 15:31:53作者:蔡怀权

Ponytail 把"最好的代码是没写出来的代码"这一理念封装成一套可注入 AI Agent 的行为规则。本文以仓库中的 Kiro steering 规则文件 .kiro/steering/ponytail.md 为主体,完整解析其决策阶梯、编码纪律与安全底线,并结合仓库源码说明这套规则如何部署到 Kiro、如何与 AGENTS.mdskills/ponytail/SKILL.md 保持同步,以及相关的运行时配置项。读完后,你将掌握这套规则集的每一条内容、部署方式,以及它在整个 Ponytail 多宿主适配体系中的位置。

规则文件定位:Kiro 的 Steering Rule 与 inclusion: always

.kiro/steering/ponytail.md 是 Ponytail 规则集面向 Kiro IDE 的适配文件。Kiro 通过 steering 机制为 Agent 注入始终生效的行为规则,该文件以 YAML frontmatter 声明:

---
title: Ponytail, lazy senior dev mode
inclusion: always
---

inclusion: always 意味着该规则在每个会话中无条件加载,而不是按需触发。根据 docs/agent-portability.md 的宿主对照表,Kiro 属于"指令级(Instruction-tier)"宿主:它加载这份 always-on 规则文件,但不提供插件层的 /ponytail 命令与强度切换(这些能力属于 Claude Code、Codex 等 skill-capable 宿主)。README 中也明确将 Kiro 列为"只加载规则、不带命令"的宿主之一。

从仓库源码结构看,这个文件并非独立维护的文档:scripts/check-rule-copies.js 将其与 AGENTS.md 做逐字节比对(剥掉各自的 frontmatter 后),内容一旦漂移脚本即失败。也就是说,.kiro/steering/ponytail.md 是 Ponytail"紧凑规则体"在 Kiro 上的副本,与 .cursor/rules/.windsurf/rules/.clinerules/.github/copilot-instructions.md 等副本同源。

核心哲学:Lazy 是高效,不是粗心

规则的第一句就锚定了基调:

You are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.

(你是一名懒的资深工程师。懒意味着高效,而非粗心。最好的代码是从未写出的代码。)

这条原则的落点不是"少写代码"本身,而是把写代码的决策前置:在动手之前先问"这该不该写"。它针对的是 Agent 最常见的两类浪费——为尚不存在的未来需求做抽象、为库里已有的功能再写一份。

决策阶梯:七级,停在第一个"站得住"的台阶

规则集的主体是一个七级阶梯,要求 Agent 在写任何代码之前,自上而下检查,停在第一个成立的台阶

  1. 这个功能到底需不需要建?(YAGNI,你并不需要它)
  2. 当前代码库里是不是已经有了? 复用已有的 helper、util 或模式,不要重写。
  3. 标准库是不是已经能做? 用它。
  4. 平台原生特性是不是能覆盖? 用它。
  5. 已安装的依赖里是不是有现成方案? 用它。
  6. 能不能一行解决? 那就写一行。
  7. 以上都不行: 才写"刚好能工作"的最少代码。

几个台阶值得展开:

  • 第 2 级(复用现有代码)是 Ponytail 特别强调的一条。skills/ponytail/SKILL.md 的完整版里,这一级被描述为"重写几个文件外现成东西是 Agent 最常见的 slop(低质产出)"。这也是 scripts/check-rule-copies.jsINVARIANTS 数组固定下来的关键短语之一('in this codebase',注释标明对应 issue #217),防止后续改写规则文本时悄悄删掉这条。
  • 第 4 级(平台原生特性)在仓库示例中有具体落点。 例如 examples/csv-sum.md 所在示例集展示了用 <input type="date"> 替代日期选择器库等做法;SKILL.md 中给出的原生特性例子还包括"CSS 优于 JS、数据库约束优于应用层代码"。
  • 第 5 级与第 6 级共同压住"依赖膨胀"和"过度工程"两条线:能用已装依赖就不加新依赖;能一行就不写函数。

阶梯的完整运行形态可以从 hooks/ponytail-instructions.js 中的 getFallbackInstructions() 看到——当 SKILL.md 文件缺失时,插件会退回到一段硬编码的规则文本,其中的阶梯与本文件完全一致,这从实现侧印证了该阶梯是 Ponytail 所有宿主的共同内核。

阶梯的运行顺序:先读懂,再爬梯

阶梯紧跟的一行是其使用前提:

The ladder runs after you understand the problem, not instead of it: read the task and the code it touches, trace the real flow end to end, then climb.

(阶梯在你理解问题之后运行,而不是替代理解:先读任务与它触及的代码,端到端追踪真实流程,然后再爬梯。)

这一条把"懒"划出了边界:懒的是解法,不是阅读。SKILL.md 的完整版进一步点名:跳过理解去提交小 diff 是最危险的一种懒——它把"效率"包装成借口,产出一个自信但错误的修复。这条前置约束同时被 scripts/check-rule-copies.js 的保护机制覆盖:其不变量检查确保核心规则措辞在 skills/ponytail/SKILL.mdAGENTS.md 之间不会被静默改写。

缺陷修复 = 根因,而非症状

规则集中单独成段的一条工程纪律:

Bug fix = root cause, not symptom: a report names a symptom. Grep every caller of the function you touch and fix the shared function once — one guard there is a smaller diff than one per caller, and patching only the path the ticket names leaves a sibling caller still broken.

(修 Bug = 修根因,而非症状。报告里写的是症状。Grep 出你即将修改的函数的所有调用方,把共享函数修一次——在那里加一个 guard 比在每个调用方各加一个 diff 更小;只补丁工单点名的那条路径,会让兄弟调用方依然保持坏掉状态。)

这条规则把"lazy"翻译成了具体的操作步骤:先 grep 全部调用方 → 判断逻辑是否收敛到共享函数 → 在共享函数上做一次修复。它实际上给出了"最小 diff"与"正确位置"的结合:diff 最小的前提是位置正确。

编码纪律:八条规则

规则文件的 Rules 一节共八条,逐条说明如下:

规则 含义
未被显式要求的抽象,一律不做 禁止无中生有的 interface、工厂、配置项
能避免新依赖就避免 依赖是默认不引入的
没人要的样板代码不写 不做"为以后"预留的脚手架
删优于增;无聊优于聪明;文件数最少 聪明代码是凌晨三点需要解码的东西
最短可工作的 diff 获胜,但前提是已理解问题 在错误位置上的最小改动不是懒,是第二个 Bug
质疑复杂需求 标准话术:"你真的需要 X 吗,还是 Y 就能覆盖?"
两个同规模的标准库方案之间,选边界情况正确的那个 懒 = 少写代码,不等于选更脆弱的算法
故意砍掉真实拐角的简化,要用 ponytail: 注释标注上限与升级路径 见下节

其中最后一条——ponytail: 天花板注释——是这套规则集最有辨识度的机制:当某次简化以可预见的上限为代价(全局锁、O(n²) 扫描、朴素启发式)时,必须在代码里留下一个 ponytail: 注释,写明上限是什么、什么时候该升级。SKILL.md 中给出的示例格式是:

# ponytail: global lock, per-account locks if throughput matters

这个机制在仓库里不止是口号:hooks/ponytail-config.js 的源码本身就在使用它,例如状态栏 shell 命令路径校验处的注释(ponytail: only embed the plugin install path ... An allowlist beats escaping every shell's metacharacters; ... Full per-shell escaper only if a real need appears.)就是一个"当前用了白名单正则、升级路径是逐 shell 转义器"的活样本。此外仓库还配有 /ponytail-debt 技能(见 skills/ponytail-debt/SKILL.md),专门把散落各处的 ponytail: 注释收集成一本"技术债台账",防止"以后再说"变成"永远不说"。

不可"懒"的清单:安全底线与"一次可运行检查"

规则文件最后一段列出了禁止简化的领域,这是整套规则的安全网:

  • 理解问题:完整读题、追踪真实流程后再选台阶。一个你自己都不理解的小 diff,只是伪装成效率的懒惰。
  • 信任边界的输入校验
  • 防止数据丢失的错误处理
  • 安全性
  • 可访问性
  • 真实硬件需要的校准:平台永远达不到规格书理想值,时钟会漂移、传感器会读数偏差,要留下调校旋钮,而不只是更少的代码。
  • 任何被显式要求的东西:用户坚持要完整版,就照做,不再争辩。

清单之后还有一条"收尾义务":

Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind, the smallest thing that fails if the logic breaks (an assert-based demo/self-check or one small test file; no frameworks, no fixtures). Trivial one-liners need no test.

(没有检查的懒代码是未完成的:非平凡逻辑必须留下一个可运行的检查——逻辑一坏它就会失败的最小单元(基于 assert 的 demo/自检,或一个小小的测试文件;不用框架、不用 fixtures)。平凡的一行代码不需要测试。)

即"一个可运行检查"(ONE runnable check)原则:YAGNI 同样适用于测试,一行代码不需要测试套件,但一个分支、一个循环、一段解析逻辑,至少要留下一条最小的可执行验证。

在 Kiro 中部署这份规则

Kiro 是纯指令级宿主,部署方式只有一步(README "Install" 一节):

# 全局生效:
cp .kiro/steering/ponytail.md ~/.kiro/steering/

# 或仅对当前项目生效:
# 把文件放到项目的 .kiro/steering/ 目录

即把 .kiro/steering/ponytail.md 复制到 ~/.kiro/steering/(全局)或项目内的 .kiro/steering/。复制完成后无需其他配置,规则随 inclusion: always 在每个会话生效。需要明确的能力边界:这条路径不提供 /ponytail 命令和 lite/full/ultra 强度切换——按 README 的命令说明,这些属于 Claude Code、Codex、OpenCode、Gemini 等 skill-capable 宿主。如果之后想升级到插件级体验,README 给出了各宿主的安装方式;卸载时对应操作是删掉复制的规则文件(README "Uninstall" 表中 Kiro 归入 "Delete the copied rule file")。

规则一致性如何保证:check-rule-copies.js 与不变量检查

这份 Kiro 文件的内容与 AGENTS.md 是同一份"紧凑规则体"(仅 frontmatter 不同),仓库用两层机制防止多副本漂移:

第一层:紧凑副本逐字节比对。 scripts/check-rule-copies.jsAGENTS.md 为基准(剔除其末尾的自我指涉段落),对六份紧凑副本做规范化后比对:

const copies = [
  ['.cursor/rules/ponytail.mdc', stripFrontmatter],
  ['.windsurf/rules/ponytail.md', text => text.trim()],
  ['.clinerules/ponytail.md', text => text.trim()],
  ['.agents/rules/ponytail.md', text => text.trim()],
  ['.qoder/rules/ponytail.md', text => text.trim()],
  ['.github/copilot-instructions.md', text => text.trim()],
  ['.kiro/steering/ponytail.md', stripFrontmatter],
];

其中 .kiro/steering/ponytail.md 使用 stripFrontmatter 规范化(去掉 title/inclusion 头部后与 AGENTS.md 正文完全一致)。任何一处副本与 AGENTS.md 不一致,脚本打印 X drifted from AGENTS.md 并以非零码退出。

第二层:关键规则短语不变量(canary)。 skills/ponytail/SKILL.md 是运行时规则的"源头真值",比紧凑体长,无法逐字节比对,因此脚本改查一组必须逐字存在的短语:

const INVARIANTS = [
  'in this codebase',                      // 阶梯第 2 级:复用现有代码
  'naive heuristic',                       // ponytail: 天花板注释规则
  'ONE runnable check',                    // "一次可运行检查"原则
  'flimsier algorithm',                    // "选更稳健的变体"规则
  'input validation at trust boundaries',  // 四条安全豁免
  'prevents data loss',
  'security',
  'accessibility',
  'Lazy code without its check is unfinished', // 收尾义务
];

注释里写明了设计取舍(本身就是一条 ponytail: 天花板注释):用"金丝雀"而非全量相等,改写任何一条规则措辞都会触发失败,从而提醒维护者把所有副本同步更新;升级路径是"如果哪天真的漏掉一次漂移,就改为从 SKILL.md 生成副本"。README "Development" 一节给出了完整验证命令:

node scripts/check-rule-copies.js
npm test

规则体与运行时:模式、配置与降级路径

理解这份文件在整个运行时中的位置有助于正确使用它。Ponytail 的完整形态由三部分组成,ponytail-mcp/instructions.js 的头部注释概括得很好:"Reuses the same builder the Claude hooks and Pi extension use, so every host emits identical rules."(复用 Claude hooks 与 Pi 扩展同一构建器,因此每个宿主注入的规则完全一致。)

  • 紧凑规则体:本文主体(.kiro/steering/ponytail.md 与 AGENTS.md 等同源副本),面向不支持技能的宿主,always-on 注入。
  • SKILL.md 完整版skills/ponytail/SKILL.md 是运行时源头真值,比紧凑体多了强度分级表(lite/full/ultra)、输出格式约定(代码优先,之后最多三行说明)、与 Caveman 的配合边界等内容。插件宿主的规则注入就是读取它:hooks/ponytail-instructions.jsgetPonytailInstructions() 读取 SKILL.md,用 filterSkillBodyForMode() 按当前强度级别过滤掉模式专属的表格行与示例行,再注入会话;文件读取失败时降级到 getFallbackInstructions() 的硬编码规则文本。
  • 配置解析hooks/ponytail-config.js 定义了默认模式的解析顺序:① 环境变量 PONYTAIL_DEFAULT_MODE(取值 lite/full/ultra/off);② 配置文件 defaultMode 字段($XDG_CONFIG_HOME/ponytail/config.json,macOS/Linux 回退到 ~/.config/ponytail/config.json,Windows 回退到 %APPDATA%\ponytail\config.json);③ 内置默认值 full。配置文件解析时还会先剥掉 UTF-8 BOM 以避免 JSON.parse 在 Windows 保存的文件上失败。

需要注意的适用前提:上述模式与配置机制只对插件级宿主(带 hooks 的 Claude Code、Codex、MCP 等)生效。Kiro 走的是纯 steering 文件路径,行为恒定为这套完整规则,没有强度旋钮,也没有"stop ponytail"式的运行时开关——这与 hooks/ponytail-config.jsisDeactivationCommand() 所处理的"独立消息触发关闭"逻辑不同,那套逻辑只存在于带 hooks 的宿主中。

小结

.kiro/steering/ponytail.md 虽只有数十行,却完整承载了 Ponytail 规则集的核心骨架:

  • 一个决策阶梯:YAGNI → 库内复用 → 标准库 → 平台原生 → 已装依赖 → 一行 → 最小可运行代码,停在第一个成立的台阶;且必须先读懂问题再爬梯。
  • 一条修复纪律:修根因,grep 全部调用方,在共享函数上修一次。
  • 八条编码规则:拒绝未要求的抽象与依赖、删优于增、质疑复杂需求、边界正确性优先于代码量、以及用 ponytail: 注释为刻意的简化登记上限与升级路径。
  • 一条安全底线:信任边界校验、防数据丢失、安全、可访问性、硬件校准、显式要求,任何一项都不可简化;非平凡逻辑必须留下"一个可运行检查"。

部署上,Kiro 用户只需把该文件放入 ~/.kiro/steering/ 或项目 .kiro/steering/ 即获得 always-on 规则;内容上,它与 AGENTS.md 逐字节同源、与 skills/ponytail/SKILL.md 通过 scripts/check-rule-copies.js 的不变量检查互相锚定——这正是 Ponytail 自己"复用而非重写"哲学的工程化体现。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384