本文是一份可复制到其它项目的 agent 协作规范。目标不是让 agent 少做事,而是让 agent 少写不必要的代码:先理解真实问题,再优先复用、删除和最小改动。
适用场景
Ponytail 适合放进项目级规则文件,例如:
AGENTS.mdCLAUDE.md.codex/或团队自定义 agent 规则目录- 项目治理文档中的 "Agent Working Rules" 章节
它适用于需求开发、缺陷修复、代码评审、重构和测试补强。它不替代项目已有的安全、发布、OpenSpec、测试或代码规范,而是作为"如何选择最小正确实现"的决策层。
核心原则
Ponytail 的原则可以概括为一句话:
高效不是跳过理解,而是在理解之后只做必要的事。
在项目里使用时,应要求 agent 先读相关代码路径,再做实现选择。小 diff 只有落在正确位置才有价值;不理解链路就做出的"小改动"通常只是把 bug 挪到另一个地方。
决策阶梯
每次准备新增代码前,按下面顺序停一下。第一个能解决问题的层级就是优先方案:
-
这个东西真的需要做吗?
- 如果需求可以通过配置、文档、现有流程或澄清边界解决,就不要写代码。
-
代码库里是否已经有现成能力?
- 先找 helper、util、service、assembler、codec、parser、test fixture、已有模式。
- 同一个语义尽量收口到一个地方,不要复制第二套。
-
标准库是否已经能解决?
- Java 项目优先考虑 JDK、Spring、Jackson/Fastjson、Apache Commons 等当前栈内能力。
-
平台或框架原生能力是否覆盖?
- Spring 配置、Bean 生命周期、校验注解、已有中间件能力优先于手写框架。
-
现有依赖是否已经能解决?
- 只使用已经引入且适合当前模块边界的依赖。
- 不为了少写几行代码新增依赖。
-
是否可以是一个小的本地改动?
- 能用局部判断解决就不新增抽象。
- 能改共享根因就不在每个调用方补丁。
-
最后才写新的最小实现。
- 只覆盖当前需求和明确的兼容边界。
- 不顺手做无关重构。
项目级规则模板
下面这段可以直接放进项目根目录的 AGENTS.md 或 CLAUDE.md:
md
## Ponytail Rules
Use Ponytail as an efficiency discipline, not as a shortcut around understanding.
Before adding code, use the first rung that works:
1. Does this need to be built at all?
2. Does the codebase already have a helper, pattern, or service for it?
3. Can the standard library or existing framework APIs do it?
4. Can an existing project dependency do it without adding a new dependency?
5. Can this be a small local change instead of a new abstraction?
6. Only then write the minimum code that solves the real flow.
Project guidance:
- Prefer deletion, reuse, and boring local fixes over new layers.
- Do not add dependencies unless the existing stack cannot reasonably solve the problem.
- Do not introduce abstractions for one caller unless the surrounding code already has that pattern.
- Fix shared root causes once instead of patching only the reported path.
- Keep changes scoped to the requested behavior and the touched module boundary.
- Mark intentional simplifications with a `ponytail:` comment only when there is a known ceiling and a clear upgrade path.
Not optional:
- Read the relevant code path before deciding the smallest change.
- Preserve validation, error handling, security, data-loss protection, and required tests.
- Non-trivial logic needs a runnable verification command or focused regression test.
- Do not use Ponytail to ignore explicit user requirements or spec SHALL rules.
在日常开发中怎么用
需求开发
需求进入实现前,先把 Ponytail 决策阶梯当作方案评估清单:
- 是否已有相同链路或邻近 lane 可以复用?
- 是否已有 DTO / codec / assembler / parser 可以扩展?
- 是否应该改共享边界,而不是在 controller、service、test 里各补一段?
- 是否需要新字段、新表、新接口,还是已有协议字段能表达?
如果需求有 OpenSpec 或 PRD,Ponytail 不能删掉 SHALL 规则。它只能帮助选择更小、更稳的实现路径。
缺陷修复
缺陷报告通常描述的是症状,不一定是根因。使用 Ponytail 时应默认:
- 复现或定位症状。
- grep 相关函数、字段、事件名和调用方。
- 找共享根因。
- 在共享边界修一次。
- 增加最小回归测试或验证命令。
不要只修用户刚好点到的路径。如果同一个 parser、normalizer、route、codec 被多个入口使用,优先修共享函数。
代码评审
评审时可以用 Ponytail 问这些问题:
- 这个新类是否只有一个调用方?
- 这个 helper 是否只是把一行代码换了个名字?
- 这个配置项是否真的需要暴露?
- 这个异常包装是否让错误更清楚,还是只增加层级?
- 这个测试是否需要完整 Spring 上下文,还是普通单测足够?
- 是否有重复逻辑可以收口到已有函数?
评审输出应优先指出可删除、可复用、可局部化的改动。
重构
Ponytail 不鼓励"大扫除式重构"。推荐顺序是:
- 先围绕当前需求修最小路径。
- 如果重复逻辑阻碍修复,再抽共享函数。
- 如果抽象已经有两个以上真实使用点,再考虑提升层级。
- 如果只是看起来更整齐,但不降低风险、不减少重复、不改善测试,就先不做。
什么不能被 Ponytail 省掉
这些内容不属于"可偷懒范围":
- 信任边界的输入校验
- 防止数据丢失的错误处理
- 鉴权、权限、脱敏和安全约束
- 金融、法务、医疗等高风险语义的准确性
- 必要的兼容逻辑
- 用户或 spec 明确要求的行为
- 非平凡逻辑的测试或可运行验证
- 发布、回滚、迁移、灰度相关安全动作
一句话:Ponytail 可以减少代码量,不能减少责任。
ponytail: 注释怎么写
只有在有意选择一个简化方案,并且知道它的上限时,才写 ponytail: 注释。
好例子:
java
// ponytail: linear scan is enough for the current <50 item payload; replace with a map if this becomes hot.
不好的例子:
java
// ponytail: simple implementation
注释必须说明:
- 为什么当前简化足够
- 上限在哪里
- 未来什么时候升级
推荐落地方式
- 在项目根目录新增或更新
AGENTS.md。 - 只放"规则入口"和 Ponytail 决策层,不复制所有团队流程。
- 如果项目已有 OpenSpec、ADR、playbook、技能目录,在
AGENTS.md里导航到它们。 - 新需求开始前,让 agent 先读相关 spec 和触达代码,再应用 Ponytail 决策阶梯。
- 提交前要求 agent 汇报:
- 复用了什么
- 没有新增什么
- 为什么这是最小正确改动
- 跑了什么验证
提交前检查清单
可以把下面清单贴到 PR 模板或 agent 收尾要求里:
- 我读过被修改链路的主要调用方。
- 我确认没有已有 helper / service / codec 可以直接复用。
- 我没有新增不必要依赖。
- 我没有为了一个调用点新增抽象。
- 我没有顺手做无关重构。
- 我保留了必要的校验、错误处理和安全边界。
- 非平凡逻辑有测试或可运行验证命令。
- 我能说明这次改动为什么是最小正确改动。
给其它项目的最小复制版
如果只想快速落地,复制下面这段即可:
md
## Ponytail
Before writing code, first ask:
1. Is this needed?
2. Does this already exist in the codebase?
3. Can the standard library or framework do it?
4. Can an existing dependency do it?
5. Can this be a local change instead of a new abstraction?
6. Only then write the smallest correct implementation.
Rules:
- Reuse before writing.
- Delete before adding.
- Shared root cause before per-caller patches.
- No new dependency unless necessary.
- No abstraction for one caller.
- Keep validation, error handling, security, data-loss protection, and tests.
- Specs and explicit user requirements still win.