Ponytail 规则集详解:让 AI Agent 以"懒资深工程师"方式写代码的 Kiro Steering 规则
Ponytail 把"最好的代码是没写出来的代码"这一理念封装成一套可注入 AI Agent 的行为规则。本文以仓库中的 Kiro steering 规则文件 .kiro/steering/ponytail.md 为主体,完整解析其决策阶梯、编码纪律与安全底线,并结合仓库源码说明这套规则如何部署到 Kiro、如何与 AGENTS.md 和 skills/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 在写任何代码之前,自上而下检查,停在第一个成立的台阶:
- 这个功能到底需不需要建?(YAGNI,你并不需要它)
- 当前代码库里是不是已经有了? 复用已有的 helper、util 或模式,不要重写。
- 标准库是不是已经能做? 用它。
- 平台原生特性是不是能覆盖? 用它。
- 已安装的依赖里是不是有现成方案? 用它。
- 能不能一行解决? 那就写一行。
- 以上都不行: 才写"刚好能工作"的最少代码。
几个台阶值得展开:
- 第 2 级(复用现有代码)是 Ponytail 特别强调的一条。 在 skills/ponytail/SKILL.md 的完整版里,这一级被描述为"重写几个文件外现成东西是 Agent 最常见的 slop(低质产出)"。这也是 scripts/check-rule-copies.js 中
INVARIANTS数组固定下来的关键短语之一('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.md 与 AGENTS.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.js 以 AGENTS.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.js 的
getPonytailInstructions()读取 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.js 中 isDeactivationCommand() 所处理的"独立消息触发关闭"逻辑不同,那套逻辑只存在于带 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 自己"复用而非重写"哲学的工程化体现。
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