你让 AI 加个日期选择,它回来 80 行:装 flatpickr、写 wrapper、补样式,还顺手跟你聊了一会儿时区。
你盯着屏幕想:我只要一个 <input type="date"> 啊。
这不是你一个人的遭遇,是几乎所有 coding agent 的通病------它不知道什么叫"够用就好" 。
上周 GitHub 周榜冒出个项目专治这个病:DietrichGebert/ponytail,一周涨了 7,499 star。在讲它之前,先得回答一个更扎心的问题------
为什么 agent 总在"过度工程"
不是它故意跟你作对。是它的训练目标和你想要的"克制"天然错位。三个根因:
1. 训练数据偏好"完整方案"。 开源代码里"装库+封装+配置"的占比远高于"一行解",模型学到的先验就是"加"。同样一句"加个日期选择",训练集里更像 flatpickr 全家桶,不是 <input type="date">。
2. RLHF 偏向"看起来用心"的输出。 人类审稿人天然给加了抽象层、校验、封装的答案更高分------"就一行"显得敷衍。于是模型被一次又一次地推向"多加点显得专业"。
3. 缺"够用就停"的奖励信号。 agent 只被奖励"完成任务",不被奖励"停止"。默认策略永远是加码------多一个 wrapper 不会扣分,少一个校验可能扣分,于是它一路加到风险最低为止。
一句话:它不是坏,是被训练目标推着往"加"的方向走。 你想要"够用就好",得自己写规则告诉它。
ponytail 给的药:懒惰阶梯
ponytail 不是新框架,是一套 ruleset(规则集)+ 命令。核心哲学一句话:动手写代码前,先爬"懒惰阶梯",停在第一个能用的档。
markdown
1. Does this need to exist? → 不需要:跳过(YAGNI)
2. Already in this codebase? → 已有:复用
3. Stdlib does it? → 标准库:用
4. Native platform feature? → 原生:用
5. Installed dependency? → 已装依赖:用
6. One line? → 一行解:跑
7. Only then: the minimum that works → 才写最小可用
日期选择器:普通 agent 第 7 档起步直接造轮子;ponytail 第 4 档就停------<input type="date">,完事。
懒,但绝不为精简牺牲正确性。 ponytail 划了红线:
信任边界校验、数据丢失处理、安全、可访问性,永远不在削减之列。
砍得掉的是"过度设计"(多余抽象层、用不上的依赖、炫技封装);砍不掉的是"该有的检查"。它要的是"最小可用且正确",不是"最小且裸奔"。
后端场景:你日常遇到的过度工程
光说日期选择器太前端。来三个后端场景,你今天就能遇到的:
场景 1:给一个低频接口加缓存
- 普通 agent 上 Redis + 连接池配置 + CacheWrapper 抽象类 + TTL 策略 + 序列化封装......120 行。
- ponytail:
static $cache = []; if (isset($cache[$key])) return $cache[$key];------3 行,进程内缓存够用了。
场景 2:记录接口错误日志
- 普通 agent 引 monolog + StreamHandler + LineFormatter + Channel,一串文件。
- ponytail:
error_log(json_encode([...$ctx]));------1 行,PHP 内置够用了。
场景 3:校验一个 ID 是不是数字
- 普通 agent 造 Validator 类 + Rule 接口 + 自定义异常 + 国际化 message。
- ponytail:
$id = (int) $id; if ($id <= 0) throw new \InvalidArgumentException();------2 行。
边界提醒 :以上"一行解"只够内部工具/低频接口/原型。一旦涉及高并发、持久化、跨进程,对应档位自动升------比如缓存一旦要多机共享就只能上 Redis,但 ponytail 第 5 档才开装依赖,不会无脑上。它不是叫你永远写一行,是叫你"先问需不需要"。
怎么用 + 命令实例
接入(覆盖 20+ agent,分两种):
- 零配置 :Windsurf / Cline / Kiro / Zed / Aider / Grok / Qoder 等,直接读仓库根
AGENTS.md即生效。 - Cursor :
git clone后node ponytail/scripts/cursor-hooks.js install。
核心命令:
| 命令 | 干什么 |
|---|---|
| `/ponytail [lite | full |
/ponytail-review |
审当前 diff,给删改清单 |
/ponytail-audit |
审全仓过度工程 |
/ponytail-debt |
把延后的快捷方式记入账本 |
/ponytail-gain |
看实测收益记分牌 |
/ponytail-review 实例输出(示例,非真实截图):
csharp
Review of diff src/Controller/UserController.php
Suggested removals (3):
L24-58 CacheWrapper class --- array cache suffices, 35 lines
L62-78 LogManager abstraction --- error_log() fits, 17 lines
L89 Unused interface --- no second implementation, 1 line
Deletable: 53 lines / 1 file
Red-line preserved: 信任边界校验、安全 --- 未动
/ponytail-gain 一段时间后会把你"少写了多少行"累成记分牌,是个看得见的收益反馈。
我的判断:谁该上、谁别上
该上 :日常 Claude Code / Cursor / Copilot,常被 agent 膨胀代码拖累,想在 CR 前先扫一遍。尤其适合这种情况------agent 写完你看不动,/ponytail-review 先给你一份"可删清单",把明显过度设计挡在提交前。
别指望:① 你的问题是"agent 根本理解不了需求"------ponytail 管"写多写少"不管"写对写错",需求没讲清它再懒也救不了。② 安全敏感场景它反而比普通 agent 更"重"(红线保护机制刻意不精简),这不是 bug 是 feature。③ 与 caveman(压缩 agent 的话)互补:caveman 治嘴、ponytail 治手,不冲突。
结语
Agent 能力强 ≠ 能落地。ponytail 给的真正启发不是某个工具,而是一条可以移植到任何 agent 的审查习惯:下次 agent 给你吐一大坨之前,先问它一句------"这玩意真的需要存在吗?"